mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Make simplify_candidate
more general
Because we will soon need to apply it to match pairs that aren't directly in a candidate.
This commit is contained in:
parent
bafad5a737
commit
e86c82296f
@ -1168,7 +1168,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// be a switch or pattern comparison.
|
||||
let mut split_or_candidate = false;
|
||||
for candidate in &mut *candidates {
|
||||
self.simplify_candidate(candidate);
|
||||
self.simplify_match_pairs(
|
||||
&mut candidate.match_pairs,
|
||||
&mut candidate.bindings,
|
||||
&mut candidate.ascriptions,
|
||||
);
|
||||
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
|
||||
&*candidate.match_pairs
|
||||
{
|
||||
@ -1181,7 +1185,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// }
|
||||
//
|
||||
// only generates a single switch.
|
||||
candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
|
||||
candidate.subcandidates =
|
||||
self.create_or_subcandidates(place, pats, candidate.has_guard);
|
||||
candidate.match_pairs.pop();
|
||||
split_or_candidate = true;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//! - `place @ (P1, P2)` can be simplified to `[place.0 @ P1, place.1 @ P2]`
|
||||
//! - `place @ x` can be simplified to `[]` by binding `x` to `place`
|
||||
//!
|
||||
//! The `simplify_candidate` routine just repeatedly applies these
|
||||
//! The `simplify_match_pairs` routine just repeatedly applies these
|
||||
//! sort of simplifications until there is nothing left to
|
||||
//! simplify. Match pairs cannot be simplified if they require some
|
||||
//! sort of test: for example, testing which variant an enum is, or
|
||||
@ -22,10 +22,15 @@ use rustc_middle::ty;
|
||||
use std::mem;
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Simplify a candidate so that all match pairs require a test.
|
||||
#[instrument(skip(self, candidate), level = "debug")]
|
||||
pub(super) fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
|
||||
debug!("{candidate:#?}");
|
||||
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
|
||||
/// ascriptions in the provided `Vec`s.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn simplify_match_pairs<'pat>(
|
||||
&mut self,
|
||||
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
||||
candidate_bindings: &mut Vec<Binding<'tcx>>,
|
||||
candidate_ascriptions: &mut Vec<Ascription<'tcx>>,
|
||||
) {
|
||||
// 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):
|
||||
//
|
||||
@ -53,25 +58,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// bindings in iter 2: [6, 7]
|
||||
//
|
||||
// final bindings: [6, 7, 4, 5, 1, 2, 3]
|
||||
let mut accumulated_bindings = mem::take(&mut candidate.bindings);
|
||||
let mut accumulated_bindings = mem::take(candidate_bindings);
|
||||
// Repeatedly simplify match pairs until fixed point is reached
|
||||
loop {
|
||||
let mut changed = false;
|
||||
for match_pair in mem::take(&mut candidate.match_pairs) {
|
||||
match self.simplify_match_pair(match_pair, candidate) {
|
||||
for match_pair in mem::take(match_pairs) {
|
||||
match self.simplify_match_pair(
|
||||
match_pair,
|
||||
candidate_bindings,
|
||||
candidate_ascriptions,
|
||||
match_pairs,
|
||||
) {
|
||||
Ok(()) => {
|
||||
changed = true;
|
||||
}
|
||||
Err(match_pair) => {
|
||||
candidate.match_pairs.push(match_pair);
|
||||
match_pairs.push(match_pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings
|
||||
candidate.bindings.extend_from_slice(&accumulated_bindings);
|
||||
mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
|
||||
candidate.bindings.clear();
|
||||
candidate_bindings.extend_from_slice(&accumulated_bindings);
|
||||
mem::swap(candidate_bindings, &mut accumulated_bindings);
|
||||
candidate_bindings.clear();
|
||||
|
||||
if !changed {
|
||||
// If we were not able to simplify anymore, done.
|
||||
@ -79,14 +89,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Store computed bindings back in `candidate`.
|
||||
mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
|
||||
// Store computed bindings back in `candidate_bindings`.
|
||||
mem::swap(candidate_bindings, &mut accumulated_bindings);
|
||||
|
||||
// Move or-patterns to the end, because they can result in us
|
||||
// creating additional candidates, so we want to test them as
|
||||
// late as possible.
|
||||
candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
||||
debug!(simplified = ?candidate, "simplify_candidate");
|
||||
match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
||||
debug!(simplified = ?match_pairs, "simplify_match_pairs");
|
||||
}
|
||||
|
||||
/// Given `candidate` that has a single or-pattern for its match-pairs,
|
||||
@ -94,19 +104,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// `pats`.
|
||||
pub(super) fn create_or_subcandidates<'pat>(
|
||||
&mut self,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
place: &PlaceBuilder<'tcx>,
|
||||
pats: &'pat [Box<Pat<'tcx>>],
|
||||
has_guard: bool,
|
||||
) -> Vec<Candidate<'pat, 'tcx>> {
|
||||
pats.iter()
|
||||
.map(|box pat| {
|
||||
let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard, self);
|
||||
self.simplify_candidate(&mut candidate);
|
||||
let mut candidate = Candidate::new(place.clone(), pat, has_guard, self);
|
||||
self.simplify_match_pairs(
|
||||
&mut candidate.match_pairs,
|
||||
&mut candidate.bindings,
|
||||
&mut candidate.ascriptions,
|
||||
);
|
||||
|
||||
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
|
||||
&*candidate.match_pairs
|
||||
{
|
||||
candidate.subcandidates = self.create_or_subcandidates(&candidate, place, pats);
|
||||
candidate.subcandidates =
|
||||
self.create_or_subcandidates(place, pats, candidate.has_guard);
|
||||
candidate.match_pairs.pop();
|
||||
}
|
||||
candidate
|
||||
@ -122,7 +137,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn simplify_match_pair<'pat>(
|
||||
&mut self,
|
||||
match_pair: MatchPair<'pat, 'tcx>,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
bindings: &mut Vec<Binding<'tcx>>,
|
||||
ascriptions: &mut Vec<Ascription<'tcx>>,
|
||||
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
||||
) -> Result<(), MatchPair<'pat, 'tcx>> {
|
||||
match match_pair.pattern.kind {
|
||||
PatKind::AscribeUserType {
|
||||
@ -131,14 +148,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
} => {
|
||||
// Apply the type ascription to the value at `match_pair.place`
|
||||
if let Some(source) = match_pair.place.try_to_place(self) {
|
||||
candidate.ascriptions.push(Ascription {
|
||||
ascriptions.push(Ascription {
|
||||
annotation: annotation.clone(),
|
||||
source,
|
||||
variance,
|
||||
});
|
||||
}
|
||||
|
||||
candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
|
||||
match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -158,7 +175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
is_primary: _,
|
||||
} => {
|
||||
if let Some(source) = match_pair.place.try_to_place(self) {
|
||||
candidate.bindings.push(Binding {
|
||||
bindings.push(Binding {
|
||||
span: match_pair.pattern.span,
|
||||
source,
|
||||
var_id: var,
|
||||
@ -168,7 +185,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
// this is the `x @ P` case; have to keep matching against `P` now
|
||||
candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
|
||||
match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -211,13 +228,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
span,
|
||||
user_ty: Box::new(user_ty),
|
||||
};
|
||||
candidate.ascriptions.push(Ascription {
|
||||
ascriptions.push(Ascription {
|
||||
annotation,
|
||||
source,
|
||||
variance: ty::Contravariant,
|
||||
});
|
||||
}
|
||||
candidate.match_pairs.push(MatchPair::new(match_pair.place, pattern, self));
|
||||
match_pairs.push(MatchPair::new(match_pair.place, pattern, self));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -233,13 +250,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
|
||||
// irrefutable
|
||||
self.prefix_slice_suffix(
|
||||
&mut candidate.match_pairs,
|
||||
&match_pair.place,
|
||||
prefix,
|
||||
slice,
|
||||
suffix,
|
||||
);
|
||||
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(match_pair)
|
||||
@ -260,9 +271,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|| !adt_def.is_variant_list_non_exhaustive());
|
||||
if irrefutable {
|
||||
let place_builder = match_pair.place.downcast(adt_def, variant_index);
|
||||
candidate
|
||||
.match_pairs
|
||||
.extend(self.field_match_pairs(place_builder, subpatterns));
|
||||
match_pairs.extend(self.field_match_pairs(place_builder, subpatterns));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(match_pair)
|
||||
@ -270,25 +279,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
PatKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||
self.prefix_slice_suffix(
|
||||
&mut candidate.match_pairs,
|
||||
&match_pair.place,
|
||||
prefix,
|
||||
slice,
|
||||
suffix,
|
||||
);
|
||||
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
PatKind::Leaf { ref subpatterns } => {
|
||||
// tuple struct, match subpats (if any)
|
||||
candidate.match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns));
|
||||
match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
PatKind::Deref { ref subpattern } => {
|
||||
let place_builder = match_pair.place.deref();
|
||||
candidate.match_pairs.push(MatchPair::new(place_builder, subpattern, self));
|
||||
match_pairs.push(MatchPair::new(place_builder, subpattern, self));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user