Skip to content

Commit d39daec

Browse files
committed
Auto merge of rust-lang#120904 - Nadrieril:match-lowering-intermediate-repr, r=<try>
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 42752cb + 45ef29c commit d39daec

File tree

5 files changed

+197
-245
lines changed

5 files changed

+197
-245
lines changed

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

+41-10
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;
@@ -951,12 +949,16 @@ struct Candidate<'pat, 'tcx> {
951949
has_guard: bool,
952950

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

956956
/// ...these bindings established...
957+
// Invariant: not mutated outside `Candidate::new()`.
957958
bindings: Vec<Binding<'tcx>>,
958959

959960
/// ...and these types asserted...
961+
// Invariant: not mutated outside `Candidate::new()`.
960962
ascriptions: Vec<Ascription<'tcx>>,
961963

962964
/// ...and if this is non-empty, one of these subcandidates also has to match...
@@ -976,19 +978,27 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
976978
place: PlaceBuilder<'tcx>,
977979
pattern: &'pat Pat<'tcx>,
978980
has_guard: bool,
979-
cx: &Builder<'_, 'tcx>,
981+
cx: &mut Builder<'_, 'tcx>,
980982
) -> Self {
981-
Candidate {
983+
let mut candidate = Candidate {
982984
span: pattern.span,
983985
has_guard,
984-
match_pairs: smallvec![MatchPair::new(place, pattern, cx)],
986+
match_pairs: vec![MatchPair::new(place, pattern, cx)],
985987
bindings: Vec::new(),
986988
ascriptions: Vec::new(),
987989
subcandidates: Vec::new(),
988990
otherwise_block: None,
989991
pre_binding_block: None,
990992
next_candidate_pre_binding_block: None,
991-
}
993+
};
994+
995+
cx.simplify_match_pairs(
996+
&mut candidate.match_pairs,
997+
&mut candidate.bindings,
998+
&mut candidate.ascriptions,
999+
);
1000+
1001+
candidate
9921002
}
9931003

9941004
/// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1044,13 +1054,18 @@ struct Ascription<'tcx> {
10441054
variance: ty::Variance,
10451055
}
10461056

1047-
#[derive(Clone, Debug)]
1057+
#[derive(Debug)]
10481058
pub(crate) struct MatchPair<'pat, 'tcx> {
1049-
// this place...
1059+
// This place...
10501060
place: PlaceBuilder<'tcx>,
10511061

10521062
// ... must match this pattern.
1063+
// Invariant: after creation and simplification in `Candidate::new()`, all match pairs must be
1064+
// simplified, i.e. require a test.
10531065
pattern: &'pat Pat<'tcx>,
1066+
1067+
/// Precomputed sub-match pairs of `pattern`.
1068+
subpairs: Vec<Self>,
10541069
}
10551070

10561071
/// See [`Test`] for more.
@@ -1172,7 +1187,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11721187
// be a switch or pattern comparison.
11731188
let mut split_or_candidate = false;
11741189
for candidate in &mut *candidates {
1175-
split_or_candidate |= self.simplify_candidate(candidate);
1190+
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
1191+
&*candidate.match_pairs
1192+
{
1193+
// Split a candidate in which the only match-pair is an or-pattern into multiple
1194+
// candidates. This is so that
1195+
//
1196+
// match x {
1197+
// 0 | 1 => { ... },
1198+
// 2 | 3 => { ... },
1199+
// }
1200+
//
1201+
// only generates a single switch.
1202+
candidate.subcandidates =
1203+
self.create_or_subcandidates(place, pats, candidate.has_guard);
1204+
candidate.match_pairs.pop();
1205+
split_or_candidate = true;
1206+
}
11761207
}
11771208

11781209
ensure_sufficient_stack(|| {

0 commit comments

Comments
 (0)