Rollup merge of #123067 - Nadrieril:always-simplify-or, r=oli-obk
match lowering: consistently merge simple or-patterns There are two places where we expand or-patterns in match lowering: the main one is `test_candidates_with_or`, and there's one in `match_candidates` that's an optimization for the simple case where the whole pattern is just one or-pattern. To reduce duplication, we merge or-pattern alternatives into a single block when possible, but we only to that in `test_candidates_with_or`. This PR fixes this oversight and merges them in `match_candidates` too. This is a part of splitting up https://github.com/rust-lang/rust/pull/122046 into smaller bits.
This commit is contained in:
commit
94e8c6c334
@ -1006,6 +1006,10 @@ struct Candidate<'pat, 'tcx> {
|
||||
/// If the candidate matches, bindings and ascriptions must be established.
|
||||
extra_data: PatternExtraData<'tcx>,
|
||||
|
||||
/// If we filled `self.subcandidate`, we store here the span of the or-pattern they came from.
|
||||
// Invariant: it is `None` iff `subcandidates.is_empty()`.
|
||||
or_span: Option<Span>,
|
||||
|
||||
/// The block before the `bindings` have been established.
|
||||
pre_binding_block: Option<BasicBlock>,
|
||||
/// The pre-binding block of the next candidate.
|
||||
@ -1028,6 +1032,7 @@ fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
|
||||
extra_data: flat_pat.extra_data,
|
||||
has_guard,
|
||||
subcandidates: Vec::new(),
|
||||
or_span: None,
|
||||
otherwise_block: None,
|
||||
pre_binding_block: None,
|
||||
next_candidate_pre_binding_block: None,
|
||||
@ -1277,7 +1282,8 @@ fn match_candidates<'pat>(
|
||||
//
|
||||
// only generates a single switch.
|
||||
candidate.subcandidates = self.create_or_subcandidates(pats, candidate.has_guard);
|
||||
candidate.match_pairs.pop();
|
||||
let first_match_pair = candidate.match_pairs.pop().unwrap();
|
||||
candidate.or_span = Some(first_match_pair.pattern.span);
|
||||
split_or_candidate = true;
|
||||
}
|
||||
}
|
||||
@ -1287,8 +1293,7 @@ fn match_candidates<'pat>(
|
||||
// At least one of the candidates has been split into subcandidates.
|
||||
// We need to change the candidate list to include those.
|
||||
let mut new_candidates = Vec::new();
|
||||
|
||||
for candidate in candidates {
|
||||
for candidate in candidates.iter_mut() {
|
||||
candidate.visit_leaves(|leaf_candidate| new_candidates.push(leaf_candidate));
|
||||
}
|
||||
self.match_simplified_candidates(
|
||||
@ -1298,6 +1303,10 @@ fn match_candidates<'pat>(
|
||||
otherwise_block,
|
||||
&mut *new_candidates,
|
||||
);
|
||||
|
||||
for candidate in candidates {
|
||||
self.merge_trivial_subcandidates(candidate);
|
||||
}
|
||||
} else {
|
||||
self.match_simplified_candidates(
|
||||
span,
|
||||
@ -1531,16 +1540,13 @@ fn test_or_pattern<'pat>(
|
||||
&mut or_candidate_refs,
|
||||
);
|
||||
candidate.subcandidates = or_candidates;
|
||||
self.merge_trivial_subcandidates(candidate, self.source_info(or_span));
|
||||
candidate.or_span = Some(or_span);
|
||||
self.merge_trivial_subcandidates(candidate);
|
||||
}
|
||||
|
||||
/// Try to merge all of the subcandidates of the given candidate into one.
|
||||
/// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
|
||||
fn merge_trivial_subcandidates(
|
||||
&mut self,
|
||||
candidate: &mut Candidate<'_, 'tcx>,
|
||||
source_info: SourceInfo,
|
||||
) {
|
||||
fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
|
||||
if candidate.subcandidates.is_empty() || candidate.has_guard {
|
||||
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
|
||||
return;
|
||||
@ -1550,7 +1556,7 @@ fn merge_trivial_subcandidates(
|
||||
|
||||
// Not `Iterator::all` because we don't want to short-circuit.
|
||||
for subcandidate in &mut candidate.subcandidates {
|
||||
self.merge_trivial_subcandidates(subcandidate, source_info);
|
||||
self.merge_trivial_subcandidates(subcandidate);
|
||||
|
||||
// FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
|
||||
can_merge &=
|
||||
@ -1559,6 +1565,8 @@ fn merge_trivial_subcandidates(
|
||||
|
||||
if can_merge {
|
||||
let any_matches = self.cfg.start_new_block();
|
||||
let or_span = candidate.or_span.take().unwrap();
|
||||
let source_info = self.source_info(or_span);
|
||||
for subcandidate in mem::take(&mut candidate.subcandidates) {
|
||||
let or_block = subcandidate.pre_binding_block.unwrap();
|
||||
self.cfg.goto(or_block, source_info, any_matches);
|
||||
|
@ -82,7 +82,8 @@ pub(super) fn create_or_subcandidates<'pat>(
|
||||
&*candidate.match_pairs
|
||||
{
|
||||
candidate.subcandidates = self.create_or_subcandidates(pats, has_guard);
|
||||
candidate.match_pairs.pop();
|
||||
let first_match_pair = candidate.match_pairs.pop().unwrap();
|
||||
candidate.or_span = Some(first_match_pair.pattern.span);
|
||||
}
|
||||
candidate
|
||||
})
|
||||
|
@ -26,18 +26,20 @@
|
||||
_3 = _1;
|
||||
_2 = move _3 as [u32; 4] (Transmute);
|
||||
StorageDead(_3);
|
||||
switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb6];
|
||||
switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb6];
|
||||
switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
switchInt(_2[2 of 4]) -> [0: bb4, 4294901760: bb5, otherwise: bb6];
|
||||
switchInt(_2[2 of 4]) -> [0: bb3, 4294901760: bb3, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_4);
|
||||
_4 = _2[3 of 4];
|
||||
StorageLive(_5);
|
||||
StorageLive(_6);
|
||||
_6 = _4;
|
||||
@ -46,27 +48,15 @@
|
||||
_0 = Option::<[u8; 4]>::Some(move _5);
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
goto -> bb7;
|
||||
goto -> bb5;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_4);
|
||||
_4 = _2[3 of 4];
|
||||
goto -> bb3;
|
||||
_0 = Option::<[u8; 4]>::None;
|
||||
goto -> bb5;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_4);
|
||||
_4 = _2[3 of 4];
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_0 = Option::<[u8; 4]>::None;
|
||||
goto -> bb7;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_2);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user