Skip to content

Commit 7410f78

Browse files
committed
Use create_or_subcandidates for all or-pattern expansions
1 parent 23c9f69 commit 7410f78

File tree

2 files changed

+37
-46
lines changed

2 files changed

+37
-46
lines changed

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

+36-36
Original file line numberDiff line numberDiff line change
@@ -1272,9 +1272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12721272
) {
12731273
let mut split_or_candidate = false;
12741274
for candidate in &mut *candidates {
1275-
if let [MatchPair { test_case: TestCase::Or { pats, .. }, .. }] =
1276-
&*candidate.match_pairs
1277-
{
1275+
if let [MatchPair { test_case: TestCase::Or { .. }, .. }] = &*candidate.match_pairs {
12781276
// Split a candidate in which the only match-pair is an or-pattern into multiple
12791277
// candidates. This is so that
12801278
//
@@ -1284,9 +1282,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12841282
// }
12851283
//
12861284
// only generates a single switch.
1287-
candidate.subcandidates = self.create_or_subcandidates(pats, candidate.has_guard);
1288-
let first_match_pair = candidate.match_pairs.pop().unwrap();
1289-
candidate.or_span = Some(first_match_pair.pattern.span);
1285+
let match_pair = candidate.match_pairs.pop().unwrap();
1286+
self.create_or_subcandidates(candidate, match_pair);
12901287
split_or_candidate = true;
12911288
}
12921289
}
@@ -1474,14 +1471,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14741471
return;
14751472
}
14761473

1477-
let match_pairs = mem::take(&mut first_candidate.match_pairs);
1478-
let (first_match_pair, remaining_match_pairs) = match_pairs.split_first().unwrap();
1479-
let TestCase::Or { ref pats } = &first_match_pair.test_case else { unreachable!() };
1480-
1474+
let first_match_pair = first_candidate.match_pairs.remove(0);
1475+
let remaining_match_pairs = mem::take(&mut first_candidate.match_pairs);
14811476
let remainder_start = self.cfg.start_new_block();
1482-
let or_span = first_match_pair.pattern.span;
14831477
// Test the alternatives of this or-pattern.
1484-
self.test_or_pattern(first_candidate, start_block, remainder_start, pats, or_span);
1478+
self.test_or_pattern(first_candidate, start_block, remainder_start, first_match_pair);
14851479

14861480
if !remaining_match_pairs.is_empty() {
14871481
// If more match pairs remain, test them after each subcandidate.
@@ -1516,52 +1510,58 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15161510
);
15171511
}
15181512

1519-
#[instrument(
1520-
skip(self, start_block, otherwise_block, or_span, candidate, pats),
1521-
level = "debug"
1522-
)]
1513+
#[instrument(skip(self, start_block, otherwise_block, candidate, match_pair), level = "debug")]
15231514
fn test_or_pattern<'pat>(
15241515
&mut self,
15251516
candidate: &mut Candidate<'pat, 'tcx>,
15261517
start_block: BasicBlock,
15271518
otherwise_block: BasicBlock,
1528-
pats: &[FlatPat<'pat, 'tcx>],
1529-
or_span: Span,
1519+
match_pair: MatchPair<'pat, 'tcx>,
15301520
) {
1531-
debug!("candidate={:#?}\npats={:#?}", candidate, pats);
1532-
let mut or_candidates: Vec<_> = pats
1533-
.iter()
1534-
.cloned()
1535-
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard))
1536-
.collect();
1537-
let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect();
1521+
let or_span = match_pair.pattern.span;
1522+
self.create_or_subcandidates(candidate, match_pair);
1523+
let mut or_candidate_refs: Vec<_> = candidate.subcandidates.iter_mut().collect();
15381524
self.match_candidates(
15391525
or_span,
15401526
or_span,
15411527
start_block,
15421528
otherwise_block,
15431529
&mut or_candidate_refs,
15441530
);
1545-
candidate.subcandidates = or_candidates;
1546-
candidate.or_span = Some(or_span);
15471531
self.merge_trivial_subcandidates(candidate);
15481532
}
15491533

1550-
/// Try to merge all of the subcandidates of the given candidate into one.
1551-
/// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
1534+
/// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
1535+
/// subcandidate. Any candidate that has been expanded that way should be passed to
1536+
/// `merge_trivial_subcandidates` after its subcandidates have been processed.
1537+
fn create_or_subcandidates<'pat>(
1538+
&mut self,
1539+
candidate: &mut Candidate<'pat, 'tcx>,
1540+
match_pair: MatchPair<'pat, 'tcx>,
1541+
) {
1542+
let TestCase::Or { pats } = match_pair.test_case else { bug!() };
1543+
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
1544+
candidate.or_span = Some(match_pair.pattern.span);
1545+
candidate.subcandidates = pats
1546+
.into_vec()
1547+
.into_iter()
1548+
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard))
1549+
.collect();
1550+
}
1551+
1552+
/// Try to merge all of the subcandidates of the given candidate into one. This avoids
1553+
/// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The or-pattern should have
1554+
/// been expanded with `create_or_subcandidates`.
15521555
fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
15531556
if candidate.subcandidates.is_empty() || candidate.has_guard {
15541557
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
15551558
return;
15561559
}
15571560

1558-
let mut can_merge = true;
1559-
for subcandidate in &mut candidate.subcandidates {
1560-
// FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1561-
can_merge &=
1562-
subcandidate.subcandidates.is_empty() && subcandidate.extra_data.is_empty();
1563-
}
1564-
1561+
// FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1562+
let can_merge = candidate.subcandidates.iter().all(|subcandidate| {
1563+
subcandidate.subcandidates.is_empty() && subcandidate.extra_data.is_empty()
1564+
});
15651565
if can_merge {
15661566
let any_matches = self.cfg.start_new_block();
15671567
let or_span = candidate.or_span.take().unwrap();

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

+1-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//! sort of test: for example, testing which variant an enum is, or
1313
//! testing a value against a constant.
1414
15-
use crate::build::matches::{Candidate, FlatPat, MatchPair, PatternExtraData, TestCase};
15+
use crate::build::matches::{MatchPair, PatternExtraData, TestCase};
1616
use crate::build::Builder;
1717

1818
use std::mem;
@@ -66,13 +66,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6666
match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
6767
debug!(simplified = ?match_pairs, "simplify_match_pairs");
6868
}
69-
70-
/// Create a new candidate for each pattern in `pats`.
71-
pub(super) fn create_or_subcandidates<'pat>(
72-
&mut self,
73-
pats: &[FlatPat<'pat, 'tcx>],
74-
has_guard: bool,
75-
) -> Vec<Candidate<'pat, 'tcx>> {
76-
pats.iter().cloned().map(|flat_pat| Candidate::from_flat_pat(flat_pat, has_guard)).collect()
77-
}
7869
}

0 commit comments

Comments
 (0)