@@ -1074,12 +1074,9 @@ struct Candidate<'pat, 'tcx> {
1074
1074
// because that would break binding consistency.
1075
1075
subcandidates : Vec < Candidate < ' pat , ' tcx > > ,
1076
1076
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` .
1078
1078
has_guard : bool ,
1079
1079
1080
- /// If the guard is `false` then branch to `otherwise_block`.
1081
- otherwise_block : Option < BasicBlock > ,
1082
-
1083
1080
/// If the candidate matches, bindings and ascriptions must be established.
1084
1081
extra_data : PatternExtraData < ' tcx > ,
1085
1082
@@ -1090,6 +1087,9 @@ struct Candidate<'pat, 'tcx> {
1090
1087
/// The block before the `bindings` have been established.
1091
1088
pre_binding_block : Option < BasicBlock > ,
1092
1089
1090
+ /// The block to branch to if the guard or a nested candidate fails to match.
1091
+ otherwise_block : Option < BasicBlock > ,
1092
+
1093
1093
/// The earliest block that has only candidates >= this one as descendents. Used for false
1094
1094
/// edges, see the doc for [`Builder::match_expr`].
1095
1095
false_edge_start_block : Option < BasicBlock > ,
@@ -1500,11 +1500,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1500
1500
1501
1501
candidate. pre_binding_block = Some ( start_block) ;
1502
1502
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) ;
1508
1506
otherwise_block
1509
1507
}
1510
1508
@@ -1591,10 +1589,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1591
1589
assert ! ( leaf_candidate. match_pairs. is_empty( ) ) ;
1592
1590
leaf_candidate. match_pairs . extend ( remaining_match_pairs. iter ( ) . cloned ( ) ) ;
1593
1591
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
+ } ;
1598
1601
self . test_candidates_with_or (
1599
1602
span,
1600
1603
scrutinee_span,
@@ -1669,6 +1672,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1669
1672
subcandidate. subcandidates . is_empty ( ) && subcandidate. extra_data . is_empty ( )
1670
1673
} ) ;
1671
1674
if can_merge {
1675
+ let mut last_otherwise = None ;
1672
1676
let any_matches = self . cfg . start_new_block ( ) ;
1673
1677
let or_span = candidate. or_span . take ( ) . unwrap ( ) ;
1674
1678
let source_info = self . source_info ( or_span) ;
@@ -1679,8 +1683,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1679
1683
for subcandidate in mem:: take ( & mut candidate. subcandidates ) {
1680
1684
let or_block = subcandidate. pre_binding_block . unwrap ( ) ;
1681
1685
self . cfg . goto ( or_block, source_info, any_matches) ;
1686
+ last_otherwise = subcandidate. otherwise_block ;
1682
1687
}
1683
1688
candidate. pre_binding_block = Some ( any_matches) ;
1689
+ assert ! ( last_otherwise. is_some( ) ) ;
1690
+ candidate. otherwise_block = last_otherwise;
1684
1691
} else {
1685
1692
// Never subcandidates may have a set of bindings inconsistent with their siblings,
1686
1693
// which would break later code. So we filter them out. Note that we can't filter out
0 commit comments