Remove the separate simplify step for match-pair trees
What remained of this simplification process has been integrated into construction of the match-pair trees.
This commit is contained in:
parent
854feae887
commit
e05df1cb5d
3 changed files with 14 additions and 71 deletions
|
@ -26,7 +26,6 @@ use crate::builder::{
|
||||||
|
|
||||||
// helper functions, broken out by category:
|
// helper functions, broken out by category:
|
||||||
mod match_pair;
|
mod match_pair;
|
||||||
mod simplify;
|
|
||||||
mod test;
|
mod test;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
@ -987,18 +986,16 @@ impl<'tcx> PatternExtraData<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A pattern in a form suitable for lowering the match tree, with all irrefutable
|
/// A pattern in a form suitable for lowering the match tree, with all irrefutable
|
||||||
/// patterns simplified away, and or-patterns sorted to the end.
|
/// patterns simplified away.
|
||||||
///
|
///
|
||||||
/// Here, "flat" indicates that the pattern's match pairs have been recursively
|
/// Here, "flat" indicates that irrefutable nodes in the pattern tree have been
|
||||||
/// simplified by [`Builder::simplify_match_pairs`]. They are not necessarily
|
/// recursively replaced with their refutable subpatterns. They are not
|
||||||
/// flat in an absolute sense.
|
/// necessarily flat in an absolute sense.
|
||||||
///
|
///
|
||||||
/// Will typically be incorporated into a [`Candidate`].
|
/// Will typically be incorporated into a [`Candidate`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct FlatPat<'tcx> {
|
struct FlatPat<'tcx> {
|
||||||
/// To match the pattern, all of these must be satisfied...
|
/// To match the pattern, all of these must be satisfied...
|
||||||
// Invariant: all the match pairs are recursively simplified.
|
|
||||||
// Invariant: or-patterns must be sorted to the end.
|
|
||||||
match_pairs: Vec<MatchPairTree<'tcx>>,
|
match_pairs: Vec<MatchPairTree<'tcx>>,
|
||||||
|
|
||||||
extra_data: PatternExtraData<'tcx>,
|
extra_data: PatternExtraData<'tcx>,
|
||||||
|
@ -1017,7 +1014,6 @@ impl<'tcx> FlatPat<'tcx> {
|
||||||
is_never: pattern.is_never_pattern(),
|
is_never: pattern.is_never_pattern(),
|
||||||
};
|
};
|
||||||
MatchPairTree::for_pattern(place, pattern, cx, &mut match_pairs, &mut extra_data);
|
MatchPairTree::for_pattern(place, pattern, cx, &mut match_pairs, &mut extra_data);
|
||||||
cx.simplify_match_pairs(&mut match_pairs, &mut extra_data);
|
|
||||||
|
|
||||||
Self { match_pairs, extra_data }
|
Self { match_pairs, extra_data }
|
||||||
}
|
}
|
||||||
|
@ -1124,7 +1120,7 @@ impl<'tcx> Candidate<'tcx> {
|
||||||
|
|
||||||
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
|
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
|
||||||
fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self {
|
fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self {
|
||||||
Candidate {
|
let mut this = Candidate {
|
||||||
match_pairs: flat_pat.match_pairs,
|
match_pairs: flat_pat.match_pairs,
|
||||||
extra_data: flat_pat.extra_data,
|
extra_data: flat_pat.extra_data,
|
||||||
has_guard,
|
has_guard,
|
||||||
|
@ -1133,7 +1129,14 @@ impl<'tcx> Candidate<'tcx> {
|
||||||
otherwise_block: None,
|
otherwise_block: None,
|
||||||
pre_binding_block: None,
|
pre_binding_block: None,
|
||||||
false_edge_start_block: None,
|
false_edge_start_block: None,
|
||||||
}
|
};
|
||||||
|
this.sort_match_pairs();
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restores the invariant that or-patterns must be sorted to the end.
|
||||||
|
fn sort_match_pairs(&mut self) {
|
||||||
|
self.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the first match pair of this candidate is an or-pattern.
|
/// Returns whether the first match pair of this candidate is an or-pattern.
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
//! Simplifying Candidates
|
|
||||||
//!
|
|
||||||
//! *Simplifying* a match pair `place @ pattern` means breaking it down
|
|
||||||
//! into bindings or other, simpler match pairs. For example:
|
|
||||||
//!
|
|
||||||
//! - `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_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
|
|
||||||
//! testing a value against a constant.
|
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use tracing::{debug, instrument};
|
|
||||||
|
|
||||||
use crate::builder::Builder;
|
|
||||||
use crate::builder::matches::{MatchPairTree, PatternExtraData, TestCase};
|
|
||||||
|
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|
||||||
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
|
|
||||||
/// ascriptions in `extra_data`.
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
pub(super) fn simplify_match_pairs(
|
|
||||||
&mut self,
|
|
||||||
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
|
|
||||||
extra_data: &mut PatternExtraData<'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):
|
|
||||||
//
|
|
||||||
// struct NonCopyStruct {
|
|
||||||
// copy_field: u32,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn foo1(x: NonCopyStruct) {
|
|
||||||
// let y @ NonCopyStruct { copy_field: z } = x;
|
|
||||||
// // the above should turn into
|
|
||||||
// let z = x.copy_field;
|
|
||||||
// let y = x;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// We therefore lower bindings from left-to-right, except we lower the `x` in `x @ pat`
|
|
||||||
// after any bindings in `pat`. This doesn't work for or-patterns: the current structure of
|
|
||||||
// match lowering forces us to lower bindings inside or-patterns last.
|
|
||||||
for mut match_pair in mem::take(match_pairs) {
|
|
||||||
self.simplify_match_pairs(&mut match_pair.subpairs, extra_data);
|
|
||||||
// Unsimplifiable pattern; we keep it.
|
|
||||||
match_pairs.push(match_pair);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
|
|
||||||
debug!(simplified = ?match_pairs, "simplify_match_pairs");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -763,7 +763,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let match_pair = candidate.match_pairs.remove(match_pair_index);
|
let match_pair = candidate.match_pairs.remove(match_pair_index);
|
||||||
candidate.match_pairs.extend(match_pair.subpairs);
|
candidate.match_pairs.extend(match_pair.subpairs);
|
||||||
// Move or-patterns to the end.
|
// Move or-patterns to the end.
|
||||||
candidate.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
|
candidate.sort_match_pairs();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue