@@ -228,6 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
228228 guard : Option < & Guard < ' tcx > > ,
229229 fake_borrow_temps : & Vec < ( Place < ' tcx > , Local ) > ,
230230 scrutinee_span : Span ,
231+ arm_span : Option < Span > ,
231232 arm_scope : Option < region:: Scope > ,
232233 ) -> BasicBlock {
233234 if candidate. subcandidates . is_empty ( ) {
@@ -239,6 +240,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
239240 guard,
240241 fake_borrow_temps,
241242 scrutinee_span,
243+ arm_span,
242244 true ,
243245 )
244246 } else {
@@ -274,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
274276 guard,
275277 & fake_borrow_temps,
276278 scrutinee_span,
279+ arm_span,
277280 schedule_drops,
278281 ) ;
279282 if arm_scope. is_none ( ) {
@@ -436,6 +439,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
436439 & fake_borrow_temps,
437440 irrefutable_pat. span ,
438441 None ,
442+ None ,
439443 )
440444 . unit ( )
441445 }
@@ -817,11 +821,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
817821 /// For an example of a case where we set `otherwise_block`, even for an
818822 /// exhaustive match consider:
819823 ///
824+ /// ```rust
820825 /// match x {
821826 /// (true, true) => (),
822827 /// (_, false) => (),
823828 /// (false, true) => (),
824829 /// }
830+ /// ```
825831 ///
826832 /// For this match, we check if `x.0` matches `true` (for the first
827833 /// arm). If that's false, we check `x.1`. If it's `true` we check if
@@ -935,11 +941,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
935941 /// Link up matched candidates. For example, if we have something like
936942 /// this:
937943 ///
944+ /// ```rust
938945 /// ...
939946 /// Some(x) if cond => ...
940947 /// Some(x) => ...
941948 /// Some(x) if cond => ...
942949 /// ...
950+ /// ```
943951 ///
944952 /// We generate real edges from:
945953 /// * `start_block` to the `prebinding_block` of the first pattern,
@@ -1517,7 +1525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15171525 /// Initializes each of the bindings from the candidate by
15181526 /// moving/copying/ref'ing the source as appropriate. Tests the guard, if
15191527 /// any, and then branches to the arm. Returns the block for the case where
1520- /// the guard fails .
1528+ /// the guard succeeds .
15211529 ///
15221530 /// Note: we do not check earlier that if there is a guard,
15231531 /// there cannot be move bindings. We avoid a use-after-move by only
@@ -1529,6 +1537,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15291537 guard : Option < & Guard < ' tcx > > ,
15301538 fake_borrows : & Vec < ( Place < ' tcx > , Local ) > ,
15311539 scrutinee_span : Span ,
1540+ arm_span : Option < Span > ,
15321541 schedule_drops : bool ,
15331542 ) -> BasicBlock {
15341543 debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
@@ -1659,15 +1668,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16591668 self . cfg . push_assign ( block, scrutinee_source_info, Place :: from ( temp) , borrow) ;
16601669 }
16611670
1662- // the block to branch to if the guard fails; if there is no
1663- // guard, this block is simply unreachable
1664- let guard = match guard {
1665- Guard :: If ( e) => self . hir . mirror ( e. clone ( ) ) ,
1671+ let ( guard_span, ( post_guard_block, otherwise_post_guard_block) ) = match guard {
1672+ Guard :: If ( e) => {
1673+ let e = self . hir . mirror ( e. clone ( ) ) ;
1674+ let source_info = self . source_info ( e. span ) ;
1675+ ( e. span , self . test_bool ( block, e, source_info) )
1676+ } ,
1677+ Guard :: IfLet ( pat, scrutinee) => {
1678+ let scrutinee_span = scrutinee. span ( ) ;
1679+ let scrutinee_place = unpack ! ( block = self . lower_scrutinee( block, scrutinee. clone( ) , scrutinee_span) ) ;
1680+ let mut guard_candidate = Candidate :: new ( scrutinee_place, & pat, false ) ;
1681+ let wildcard = Pat :: wildcard_from_ty ( pat. ty ) ;
1682+ let mut otherwise_candidate = Candidate :: new ( scrutinee_place, & wildcard, false ) ;
1683+ let fake_borrow_temps =
1684+ self . lower_match_tree ( block, pat. span , false , & mut [ & mut guard_candidate, & mut otherwise_candidate] ) ;
1685+ self . declare_bindings (
1686+ None ,
1687+ pat. span . to ( arm_span. unwrap ( ) ) ,
1688+ pat,
1689+ ArmHasGuard ( false ) ,
1690+ Some ( ( Some ( & scrutinee_place) , scrutinee. span ( ) ) ) ,
1691+ ) ;
1692+ let post_guard_block = self . bind_pattern (
1693+ self . source_info ( pat. span ) ,
1694+ guard_candidate,
1695+ None ,
1696+ & fake_borrow_temps,
1697+ scrutinee. span ( ) ,
1698+ None ,
1699+ None ,
1700+ ) ;
1701+ let otherwise_post_guard_block = otherwise_candidate. pre_binding_block . unwrap ( ) ;
1702+ ( scrutinee_span, ( post_guard_block, otherwise_post_guard_block) )
1703+ }
16661704 } ;
1667- let source_info = self . source_info ( guard. span ) ;
1668- let guard_end = self . source_info ( tcx. sess . source_map ( ) . end_point ( guard. span ) ) ;
1669- let ( post_guard_block, otherwise_post_guard_block) =
1670- self . test_bool ( block, guard, source_info) ;
1705+ let source_info = self . source_info ( guard_span) ;
1706+ let guard_end = self . source_info ( tcx. sess . source_map ( ) . end_point ( guard_span) ) ;
16711707 let guard_frame = self . guard_context . pop ( ) . unwrap ( ) ;
16721708 debug ! ( "Exiting guard building context with locals: {:?}" , guard_frame) ;
16731709
0 commit comments