Skip to content

Commit 5fe2ca6

Browse files
committed
Always set otherwise_blocks
1 parent e74b30e commit 5fe2ca6

File tree

1 file changed

+20
-13
lines changed
  • compiler/rustc_mir_build/src/build/matches

1 file changed

+20
-13
lines changed

compiler/rustc_mir_build/src/build/matches/mod.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)