Move or-pattern expansion inside the main part of the algorithm
This commit is contained in:
parent
bff4d213fa
commit
c5062f7318
@ -1119,6 +1119,11 @@ fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the first match pair of this candidate is an or-pattern.
|
||||||
|
fn starts_with_or_pattern(&self) -> bool {
|
||||||
|
matches!(&*self.match_pairs, [MatchPair { test_case: TestCase::Or { .. }, .. }, ..])
|
||||||
|
}
|
||||||
|
|
||||||
/// Visit the leaf candidates (those with no subcandidates) contained in
|
/// Visit the leaf candidates (those with no subcandidates) contained in
|
||||||
/// this candidate.
|
/// this candidate.
|
||||||
fn visit_leaves<'a>(&'a mut self, mut visit_leaf: impl FnMut(&'a mut Self)) {
|
fn visit_leaves<'a>(&'a mut self, mut visit_leaf: impl FnMut(&'a mut Self)) {
|
||||||
@ -1435,39 +1440,20 @@ fn match_candidates(
|
|||||||
otherwise_block: BasicBlock,
|
otherwise_block: BasicBlock,
|
||||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
||||||
) {
|
) {
|
||||||
// If any candidate starts with an or-pattern, we have to expand the or-pattern before we
|
|
||||||
// can proceed further.
|
|
||||||
let expand_ors = candidates.iter().any(|candidate| {
|
|
||||||
matches!(
|
|
||||||
&*candidate.match_pairs,
|
|
||||||
[MatchPair { test_case: TestCase::Or { .. }, .. }, ..]
|
|
||||||
)
|
|
||||||
});
|
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
if !expand_ors {
|
self.match_candidates_with_enough_stack(
|
||||||
// No candidates start with an or-pattern, we can continue.
|
span,
|
||||||
self.match_expanded_candidates(
|
scrutinee_span,
|
||||||
span,
|
start_block,
|
||||||
scrutinee_span,
|
otherwise_block,
|
||||||
start_block,
|
candidates,
|
||||||
otherwise_block,
|
)
|
||||||
candidates,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
self.expand_and_match_or_candidates(
|
|
||||||
span,
|
|
||||||
scrutinee_span,
|
|
||||||
start_block,
|
|
||||||
otherwise_block,
|
|
||||||
candidates,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct the decision tree for `candidates`. Caller must ensure that no candidate in
|
/// Construct the decision tree for `candidates`. Don't call this, call `match_candidates`
|
||||||
/// `candidates` starts with an or-pattern.
|
/// instead to reserve sufficient stack space.
|
||||||
fn match_expanded_candidates(
|
fn match_candidates_with_enough_stack(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
@ -1492,12 +1478,17 @@ fn match_expanded_candidates(
|
|||||||
// The first candidate has satisfied all its match pairs; we link it up and continue
|
// The first candidate has satisfied all its match pairs; we link it up and continue
|
||||||
// with the remaining candidates.
|
// with the remaining candidates.
|
||||||
start_block = self.select_matched_candidate(first, start_block);
|
start_block = self.select_matched_candidate(first, start_block);
|
||||||
self.match_expanded_candidates(
|
self.match_candidates(span, scrutinee_span, start_block, otherwise_block, remaining)
|
||||||
|
}
|
||||||
|
candidates if candidates.iter().any(|candidate| candidate.starts_with_or_pattern()) => {
|
||||||
|
// If any candidate starts with an or-pattern, we have to expand the or-pattern before we
|
||||||
|
// can proceed further.
|
||||||
|
self.expand_and_match_or_candidates(
|
||||||
span,
|
span,
|
||||||
scrutinee_span,
|
scrutinee_span,
|
||||||
start_block,
|
start_block,
|
||||||
otherwise_block,
|
otherwise_block,
|
||||||
remaining,
|
candidates,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
candidates => {
|
candidates => {
|
||||||
@ -1591,9 +1582,7 @@ fn expand_and_match_or_candidates(
|
|||||||
let mut expand_until = 0;
|
let mut expand_until = 0;
|
||||||
for (i, candidate) in candidates.iter().enumerate() {
|
for (i, candidate) in candidates.iter().enumerate() {
|
||||||
expand_until = i + 1;
|
expand_until = i + 1;
|
||||||
if candidate.match_pairs.len() > 1
|
if candidate.match_pairs.len() > 1 && candidate.starts_with_or_pattern() {
|
||||||
&& matches!(&candidate.match_pairs[0].test_case, TestCase::Or { .. })
|
|
||||||
{
|
|
||||||
// The candidate has an or-pattern as well as more match pairs: we must
|
// The candidate has an or-pattern as well as more match pairs: we must
|
||||||
// split the candidates list here.
|
// split the candidates list here.
|
||||||
break;
|
break;
|
||||||
@ -1604,8 +1593,7 @@ fn expand_and_match_or_candidates(
|
|||||||
// Expand one level of or-patterns for each candidate in `candidates_to_expand`.
|
// Expand one level of or-patterns for each candidate in `candidates_to_expand`.
|
||||||
let mut expanded_candidates = Vec::new();
|
let mut expanded_candidates = Vec::new();
|
||||||
for candidate in candidates_to_expand.iter_mut() {
|
for candidate in candidates_to_expand.iter_mut() {
|
||||||
if let [MatchPair { test_case: TestCase::Or { .. }, .. }, ..] = &*candidate.match_pairs
|
if candidate.starts_with_or_pattern() {
|
||||||
{
|
|
||||||
let or_match_pair = candidate.match_pairs.remove(0);
|
let or_match_pair = candidate.match_pairs.remove(0);
|
||||||
// Expand the or-pattern into subcandidates.
|
// Expand the or-pattern into subcandidates.
|
||||||
self.create_or_subcandidates(candidate, or_match_pair);
|
self.create_or_subcandidates(candidate, or_match_pair);
|
||||||
|
Loading…
Reference in New Issue
Block a user