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:
Zalathar 2025-03-05 23:26:00 +11:00
parent 854feae887
commit e05df1cb5d
3 changed files with 14 additions and 71 deletions

View file

@ -26,7 +26,6 @@ use crate::builder::{
// helper functions, broken out by category:
mod match_pair;
mod simplify;
mod test;
mod util;
@ -987,18 +986,16 @@ impl<'tcx> PatternExtraData<'tcx> {
}
/// 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
/// simplified by [`Builder::simplify_match_pairs`]. They are not necessarily
/// flat in an absolute sense.
/// Here, "flat" indicates that irrefutable nodes in the pattern tree have been
/// recursively replaced with their refutable subpatterns. They are not
/// necessarily flat in an absolute sense.
///
/// Will typically be incorporated into a [`Candidate`].
#[derive(Debug, Clone)]
struct FlatPat<'tcx> {
/// 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>>,
extra_data: PatternExtraData<'tcx>,
@ -1017,7 +1014,6 @@ impl<'tcx> FlatPat<'tcx> {
is_never: pattern.is_never_pattern(),
};
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 }
}
@ -1124,7 +1120,7 @@ impl<'tcx> Candidate<'tcx> {
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self {
Candidate {
let mut this = Candidate {
match_pairs: flat_pat.match_pairs,
extra_data: flat_pat.extra_data,
has_guard,
@ -1133,7 +1129,14 @@ impl<'tcx> Candidate<'tcx> {
otherwise_block: None,
pre_binding_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.

View file

@ -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");
}
}

View file

@ -763,7 +763,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let match_pair = candidate.match_pairs.remove(match_pair_index);
candidate.match_pairs.extend(match_pair.subpairs);
// Move or-patterns to the end.
candidate.match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
candidate.sort_match_pairs();
}
ret