@@ -1074,12 +1074,9 @@ struct Candidate<'pat, 'tcx> {
10741074 // because that would break binding consistency.
10751075 subcandidates : Vec < Candidate < ' pat , ' tcx > > ,
10761076
1077- /// ...and the guard must be evaluated if there is one .
1077+ /// ...and if there is a guard it must be evaluated; if it's `false` then branch to `otherwise_block` .
10781078 has_guard : bool ,
10791079
1080- /// If the guard is `false` then branch to `otherwise_block`.
1081- otherwise_block : Option < BasicBlock > ,
1082-
10831080 /// If the candidate matches, bindings and ascriptions must be established.
10841081 extra_data : PatternExtraData < ' tcx > ,
10851082
@@ -1090,6 +1087,9 @@ struct Candidate<'pat, 'tcx> {
10901087 /// The block before the `bindings` have been established.
10911088 pre_binding_block : Option < BasicBlock > ,
10921089
1090+ /// The block to branch to if the guard or a nested candidate fails to match.
1091+ otherwise_block : Option < BasicBlock > ,
1092+
10931093 /// The earliest block that has only candidates >= this one as descendents. Used for false
10941094 /// edges, see the doc for [`Builder::match_expr`].
10951095 false_edge_start_block : Option < BasicBlock > ,
@@ -1500,11 +1500,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15001500
15011501 candidate. pre_binding_block = Some ( start_block) ;
15021502 let otherwise_block = self . cfg . start_new_block ( ) ;
1503- if candidate. has_guard {
1504- // Create the otherwise block for this candidate, which is the
1505- // pre-binding block for the next candidate.
1506- candidate. otherwise_block = Some ( otherwise_block) ;
1507- }
1503+ // Create the otherwise block for this candidate, which is the
1504+ // pre-binding block for the next candidate.
1505+ candidate. otherwise_block = Some ( otherwise_block) ;
15081506 otherwise_block
15091507 }
15101508
@@ -1591,10 +1589,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15911589 assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
15921590 leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
15931591 let or_start = leaf_candidate. pre_binding_block . unwrap ( ) ;
1594- // In a case like `(a | b, c | d)`, if `a` succeeds and `c | d` fails, we know `(b,
1595- // c | d)` will fail too. If there is no guard, we skip testing of `b` by branching
1596- // directly to `remainder_start`. If there is a guard, we have to try `(b, c | d)`.
1597- let or_otherwise = leaf_candidate. otherwise_block . unwrap_or ( remainder_start) ;
1592+ // In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q,
1593+ // R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching
1594+ // directly to `remainder_start`. If there is a guard, `or_otherwise` can be reached
1595+ // by guard failure as well, so we can't skip `Q`.
1596+ let or_otherwise = if leaf_candidate. has_guard {
1597+ leaf_candidate. otherwise_block . unwrap ( )
1598+ } else {
1599+ remainder_start
1600+ } ;
15981601 self . test_candidates_with_or (
15991602 span,
16001603 scrutinee_span,
@@ -1669,6 +1672,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16691672 subcandidate. subcandidates . is_empty ( ) && subcandidate. extra_data . is_empty ( )
16701673 } ) ;
16711674 if can_merge {
1675+ let mut last_otherwise = None ;
16721676 let any_matches = self . cfg . start_new_block ( ) ;
16731677 let or_span = candidate. or_span . take ( ) . unwrap ( ) ;
16741678 let source_info = self . source_info ( or_span) ;
@@ -1679,8 +1683,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16791683 for subcandidate in mem:: take ( & mut candidate. subcandidates ) {
16801684 let or_block = subcandidate. pre_binding_block . unwrap ( ) ;
16811685 self . cfg . goto ( or_block, source_info, any_matches) ;
1686+ last_otherwise = subcandidate. otherwise_block ;
16821687 }
16831688 candidate. pre_binding_block = Some ( any_matches) ;
1689+ assert ! ( last_otherwise. is_some( ) ) ;
1690+ candidate. otherwise_block = last_otherwise;
16841691 } else {
16851692 // Never subcandidates may have a set of bindings inconsistent with their siblings,
16861693 // which would break later code. So we filter them out. Note that we can't filter out
0 commit comments