Skip to content

Commit 4e65074

Browse files
committed
Auto merge of #120904 - Nadrieril:match-lowering-intermediate-repr, r=matthewjasper
match lowering: eagerly simplify match pairs This removes one important complication from match lowering. Before this, match pair simplification (which includes collecting bindings and type ascriptions) was intertwined with the whole match lowering algorithm. I'm avoiding this by storing in each `MatchPair` the sub-`MatchPair`s that correspond to its subfields. This makes it possible to simplify everything (except or-patterns) in `Candidate::new()`. This should open up further simplifications. It will also give us proper control over the order of bindings. r? `@matthewjasper`
2 parents 2dc0170 + 328c776 commit 4e65074

File tree

5 files changed

+219
-260
lines changed

5 files changed

+219
-260
lines changed

compiler/rustc_mir_build/src/build/matches/mod.rs

+41-13
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
2222
use rustc_span::symbol::Symbol;
2323
use rustc_span::{BytePos, Pos, Span};
2424
use rustc_target::abi::VariantIdx;
25-
use smallvec::{smallvec, SmallVec};
26-
2725
// helper functions, broken out by category:
2826
mod simplify;
2927
mod test;
@@ -949,12 +947,16 @@ struct Candidate<'pat, 'tcx> {
949947
has_guard: bool,
950948

951949
/// All of these must be satisfied...
952-
match_pairs: SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
950+
// Invariant: all the `MatchPair`s are recursively simplified.
951+
// Invariant: or-patterns must be sorted at the end.
952+
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
953953

954954
/// ...these bindings established...
955+
// Invariant: not mutated outside `Candidate::new()`.
955956
bindings: Vec<Binding<'tcx>>,
956957

957958
/// ...and these types asserted...
959+
// Invariant: not mutated outside `Candidate::new()`.
958960
ascriptions: Vec<Ascription<'tcx>>,
959961

960962
/// ...and if this is non-empty, one of these subcandidates also has to match...
@@ -974,19 +976,27 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
974976
place: PlaceBuilder<'tcx>,
975977
pattern: &'pat Pat<'tcx>,
976978
has_guard: bool,
977-
cx: &Builder<'_, 'tcx>,
979+
cx: &mut Builder<'_, 'tcx>,
978980
) -> Self {
979-
Candidate {
981+
let mut candidate = Candidate {
980982
span: pattern.span,
981983
has_guard,
982-
match_pairs: smallvec![MatchPair::new(place, pattern, cx)],
984+
match_pairs: vec![MatchPair::new(place, pattern, cx)],
983985
bindings: Vec::new(),
984986
ascriptions: Vec::new(),
985987
subcandidates: Vec::new(),
986988
otherwise_block: None,
987989
pre_binding_block: None,
988990
next_candidate_pre_binding_block: None,
989-
}
991+
};
992+
993+
cx.simplify_match_pairs(
994+
&mut candidate.match_pairs,
995+
&mut candidate.bindings,
996+
&mut candidate.ascriptions,
997+
);
998+
999+
candidate
9901000
}
9911001

9921002
/// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1042,13 +1052,18 @@ struct Ascription<'tcx> {
10421052
variance: ty::Variance,
10431053
}
10441054

1045-
#[derive(Clone, Debug)]
1055+
#[derive(Debug)]
10461056
pub(crate) struct MatchPair<'pat, 'tcx> {
1047-
// this place...
1057+
// This place...
10481058
place: PlaceBuilder<'tcx>,
10491059

10501060
// ... must match this pattern.
1061+
// Invariant: after creation and simplification in `Candidate::new()`, all match pairs must be
1062+
// simplified, i.e. require a test.
10511063
pattern: &'pat Pat<'tcx>,
1064+
1065+
/// Precomputed sub-match pairs of `pattern`.
1066+
subpairs: Vec<Self>,
10521067
}
10531068

10541069
/// See [`Test`] for more.
@@ -1165,12 +1180,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11651180
candidates: &mut [&mut Candidate<'pat, 'tcx>],
11661181
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
11671182
) {
1168-
// Start by simplifying candidates. Once this process is complete, all
1169-
// the match pairs which remain require some form of test, whether it
1170-
// be a switch or pattern comparison.
11711183
let mut split_or_candidate = false;
11721184
for candidate in &mut *candidates {
1173-
split_or_candidate |= self.simplify_candidate(candidate);
1185+
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
1186+
&*candidate.match_pairs
1187+
{
1188+
// Split a candidate in which the only match-pair is an or-pattern into multiple
1189+
// candidates. This is so that
1190+
//
1191+
// match x {
1192+
// 0 | 1 => { ... },
1193+
// 2 | 3 => { ... },
1194+
// }
1195+
//
1196+
// only generates a single switch.
1197+
candidate.subcandidates =
1198+
self.create_or_subcandidates(place, pats, candidate.has_guard);
1199+
candidate.match_pairs.pop();
1200+
split_or_candidate = true;
1201+
}
11741202
}
11751203

11761204
ensure_sufficient_stack(|| {

0 commit comments

Comments
 (0)