Move Or
test outside of simplify_candidate
This commit is contained in:
parent
48b83e8a63
commit
bafad5a737
@ -1168,7 +1168,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// be a switch or pattern comparison.
|
// be a switch or pattern comparison.
|
||||||
let mut split_or_candidate = false;
|
let mut split_or_candidate = false;
|
||||||
for candidate in &mut *candidates {
|
for candidate in &mut *candidates {
|
||||||
split_or_candidate |= self.simplify_candidate(candidate);
|
self.simplify_candidate(candidate);
|
||||||
|
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
|
||||||
|
&*candidate.match_pairs
|
||||||
|
{
|
||||||
|
// Split a candidate in which the only match-pair is an or-pattern into multiple
|
||||||
|
// candidates. This is so that
|
||||||
|
//
|
||||||
|
// match x {
|
||||||
|
// 0 | 1 => { ... },
|
||||||
|
// 2 | 3 => { ... },
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// only generates a single switch.
|
||||||
|
candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
|
||||||
|
candidate.match_pairs.pop();
|
||||||
|
split_or_candidate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
|
@ -23,23 +23,8 @@ use std::mem;
|
|||||||
|
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Simplify a candidate so that all match pairs require a test.
|
/// Simplify a candidate so that all match pairs require a test.
|
||||||
///
|
|
||||||
/// This method will also split a candidate, in which the only
|
|
||||||
/// match-pair is an or-pattern, into multiple candidates.
|
|
||||||
/// This is so that
|
|
||||||
///
|
|
||||||
/// match x {
|
|
||||||
/// 0 | 1 => { ... },
|
|
||||||
/// 2 | 3 => { ... },
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// only generates a single switch. If this happens this method returns
|
|
||||||
/// `true`.
|
|
||||||
#[instrument(skip(self, candidate), level = "debug")]
|
#[instrument(skip(self, candidate), level = "debug")]
|
||||||
pub(super) fn simplify_candidate<'pat>(
|
pub(super) fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
|
||||||
&mut self,
|
|
||||||
candidate: &mut Candidate<'pat, 'tcx>,
|
|
||||||
) -> bool {
|
|
||||||
debug!("{candidate:#?}");
|
debug!("{candidate:#?}");
|
||||||
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
|
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
|
||||||
// bindings in `pat` before `x`. E.g. (#69971):
|
// bindings in `pat` before `x`. E.g. (#69971):
|
||||||
@ -97,30 +82,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// Store computed bindings back in `candidate`.
|
// Store computed bindings back in `candidate`.
|
||||||
mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
|
mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
|
||||||
|
|
||||||
let did_expand_or =
|
|
||||||
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
|
|
||||||
&*candidate.match_pairs
|
|
||||||
{
|
|
||||||
candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
|
|
||||||
candidate.match_pairs.clear();
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
// Move or-patterns to the end, because they can result in us
|
// Move or-patterns to the end, because they can result in us
|
||||||
// creating additional candidates, so we want to test them as
|
// creating additional candidates, so we want to test them as
|
||||||
// late as possible.
|
// late as possible.
|
||||||
candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
||||||
debug!(simplified = ?candidate, "simplify_candidate");
|
debug!(simplified = ?candidate, "simplify_candidate");
|
||||||
|
|
||||||
did_expand_or
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given `candidate` that has a single or-pattern for its match-pairs,
|
/// Given `candidate` that has a single or-pattern for its match-pairs,
|
||||||
/// creates a fresh candidate for each of its input subpatterns passed via
|
/// creates a fresh candidate for each of its input subpatterns passed via
|
||||||
/// `pats`.
|
/// `pats`.
|
||||||
fn create_or_subcandidates<'pat>(
|
pub(super) fn create_or_subcandidates<'pat>(
|
||||||
&mut self,
|
&mut self,
|
||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
place: &PlaceBuilder<'tcx>,
|
place: &PlaceBuilder<'tcx>,
|
||||||
@ -130,6 +102,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
.map(|box pat| {
|
.map(|box pat| {
|
||||||
let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard, self);
|
let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard, self);
|
||||||
self.simplify_candidate(&mut candidate);
|
self.simplify_candidate(&mut candidate);
|
||||||
|
|
||||||
|
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
|
||||||
|
&*candidate.match_pairs
|
||||||
|
{
|
||||||
|
candidate.subcandidates = self.create_or_subcandidates(&candidate, place, pats);
|
||||||
|
candidate.match_pairs.pop();
|
||||||
|
}
|
||||||
candidate
|
candidate
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user