@@ -228,6 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
228
228
guard : Option < & Guard < ' tcx > > ,
229
229
fake_borrow_temps : & Vec < ( Place < ' tcx > , Local ) > ,
230
230
scrutinee_span : Span ,
231
+ arm_span : Option < Span > ,
231
232
arm_scope : Option < region:: Scope > ,
232
233
) -> BasicBlock {
233
234
if candidate. subcandidates . is_empty ( ) {
@@ -239,6 +240,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
239
240
guard,
240
241
fake_borrow_temps,
241
242
scrutinee_span,
243
+ arm_span,
242
244
true ,
243
245
)
244
246
} else {
@@ -274,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
274
276
guard,
275
277
& fake_borrow_temps,
276
278
scrutinee_span,
279
+ arm_span,
277
280
schedule_drops,
278
281
) ;
279
282
if arm_scope. is_none ( ) {
@@ -436,6 +439,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
436
439
& fake_borrow_temps,
437
440
irrefutable_pat. span ,
438
441
None ,
442
+ None ,
439
443
)
440
444
. unit ( )
441
445
}
@@ -817,11 +821,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
817
821
/// For an example of a case where we set `otherwise_block`, even for an
818
822
/// exhaustive match consider:
819
823
///
824
+ /// ```rust
820
825
/// match x {
821
826
/// (true, true) => (),
822
827
/// (_, false) => (),
823
828
/// (false, true) => (),
824
829
/// }
830
+ /// ```
825
831
///
826
832
/// For this match, we check if `x.0` matches `true` (for the first
827
833
/// 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> {
935
941
/// Link up matched candidates. For example, if we have something like
936
942
/// this:
937
943
///
944
+ /// ```rust
938
945
/// ...
939
946
/// Some(x) if cond => ...
940
947
/// Some(x) => ...
941
948
/// Some(x) if cond => ...
942
949
/// ...
950
+ /// ```
943
951
///
944
952
/// We generate real edges from:
945
953
/// * `start_block` to the `prebinding_block` of the first pattern,
@@ -1517,7 +1525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1517
1525
/// Initializes each of the bindings from the candidate by
1518
1526
/// moving/copying/ref'ing the source as appropriate. Tests the guard, if
1519
1527
/// any, and then branches to the arm. Returns the block for the case where
1520
- /// the guard fails .
1528
+ /// the guard succeeds .
1521
1529
///
1522
1530
/// Note: we do not check earlier that if there is a guard,
1523
1531
/// there cannot be move bindings. We avoid a use-after-move by only
@@ -1529,6 +1537,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1529
1537
guard : Option < & Guard < ' tcx > > ,
1530
1538
fake_borrows : & Vec < ( Place < ' tcx > , Local ) > ,
1531
1539
scrutinee_span : Span ,
1540
+ arm_span : Option < Span > ,
1532
1541
schedule_drops : bool ,
1533
1542
) -> BasicBlock {
1534
1543
debug ! ( "bind_and_guard_matched_candidate(candidate={:?})" , candidate) ;
@@ -1659,15 +1668,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1659
1668
self . cfg . push_assign ( block, scrutinee_source_info, Place :: from ( temp) , borrow) ;
1660
1669
}
1661
1670
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
+ }
1666
1704
} ;
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) ) ;
1671
1707
let guard_frame = self . guard_context . pop ( ) . unwrap ( ) ;
1672
1708
debug ! ( "Exiting guard building context with locals: {:?}" , guard_frame) ;
1673
1709
0 commit comments