Skip to content

Commit 2966611

Browse files
committed
Pre-simplify or-patterns too
1 parent b6e4299 commit 2966611

File tree

3 files changed

+67
-40
lines changed

3 files changed

+67
-40
lines changed

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

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
938938
}
939939
}
940940

941+
/// A pattern in a form suitable for generating code.
942+
#[derive(Debug, Clone)]
943+
struct FlatPat<'pat, 'tcx> {
944+
/// [`Span`] of the original pattern.
945+
span: Span,
946+
947+
/// To match the pattern, all of these must be satisfied...
948+
// Invariant: all the `MatchPair`s are recursively simplified.
949+
// Invariant: or-patterns must be sorted to the end.
950+
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
951+
952+
/// ...these bindings established...
953+
bindings: Vec<Binding<'tcx>>,
954+
955+
/// ...and these types asserted.
956+
ascriptions: Vec<Ascription<'tcx>>,
957+
}
958+
959+
impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
960+
fn new(
961+
place: PlaceBuilder<'tcx>,
962+
pattern: &'pat Pat<'tcx>,
963+
cx: &mut Builder<'_, 'tcx>,
964+
) -> Self {
965+
let mut match_pairs = vec![MatchPair::new(place, pattern, cx)];
966+
let mut bindings = Vec::new();
967+
let mut ascriptions = Vec::new();
968+
969+
cx.simplify_match_pairs(&mut match_pairs, &mut bindings, &mut ascriptions);
970+
971+
FlatPat { span: pattern.span, match_pairs, bindings, ascriptions }
972+
}
973+
}
974+
941975
#[derive(Debug)]
942976
struct Candidate<'pat, 'tcx> {
943977
/// [`Span`] of the original pattern that gave rise to this candidate.
@@ -952,11 +986,11 @@ struct Candidate<'pat, 'tcx> {
952986
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
953987

954988
/// ...these bindings established...
955-
// Invariant: not mutated outside `Candidate::new()`.
989+
// Invariant: not mutated after candidate creation.
956990
bindings: Vec<Binding<'tcx>>,
957991

958992
/// ...and these types asserted...
959-
// Invariant: not mutated outside `Candidate::new()`.
993+
// Invariant: not mutated after candidate creation.
960994
ascriptions: Vec<Ascription<'tcx>>,
961995

962996
/// ...and if this is non-empty, one of these subcandidates also has to match...
@@ -978,25 +1012,21 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
9781012
has_guard: bool,
9791013
cx: &mut Builder<'_, 'tcx>,
9801014
) -> Self {
981-
let mut candidate = Candidate {
982-
span: pattern.span,
1015+
Self::from_flat_pat(FlatPat::new(place, pattern, cx), has_guard)
1016+
}
1017+
1018+
fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
1019+
Candidate {
1020+
span: flat_pat.span,
1021+
match_pairs: flat_pat.match_pairs,
1022+
bindings: flat_pat.bindings,
1023+
ascriptions: flat_pat.ascriptions,
9831024
has_guard,
984-
match_pairs: vec![MatchPair::new(place, pattern, cx)],
985-
bindings: Vec::new(),
986-
ascriptions: Vec::new(),
9871025
subcandidates: Vec::new(),
9881026
otherwise_block: None,
9891027
pre_binding_block: None,
9901028
next_candidate_pre_binding_block: None,
991-
};
992-
993-
cx.simplify_match_pairs(
994-
&mut candidate.match_pairs,
995-
&mut candidate.bindings,
996-
&mut candidate.ascriptions,
997-
);
998-
999-
candidate
1029+
}
10001030
}
10011031

10021032
/// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1059,7 +1089,7 @@ enum TestCase<'pat, 'tcx> {
10591089
Constant { value: mir::Const<'tcx> },
10601090
Range(&'pat PatRange<'tcx>),
10611091
Slice { len: usize, variable_length: bool },
1062-
Or,
1092+
Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
10631093
}
10641094

10651095
#[derive(Debug, Clone)]
@@ -1217,7 +1247,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12171247
) {
12181248
let mut split_or_candidate = false;
12191249
for candidate in &mut *candidates {
1220-
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
1250+
if let [MatchPair { test_case: TestCase::Or { pats, .. }, .. }] =
12211251
&*candidate.match_pairs
12221252
{
12231253
// Split a candidate in which the only match-pair is an or-pattern into multiple
@@ -1229,8 +1259,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12291259
// }
12301260
//
12311261
// only generates a single switch.
1232-
candidate.subcandidates =
1233-
self.create_or_subcandidates(place, pats, candidate.has_guard);
1262+
candidate.subcandidates = self.create_or_subcandidates(pats, candidate.has_guard);
12341263
candidate.match_pairs.pop();
12351264
split_or_candidate = true;
12361265
}
@@ -1449,7 +1478,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14491478
) {
14501479
let (first_candidate, remaining_candidates) = candidates.split_first_mut().unwrap();
14511480
assert!(first_candidate.subcandidates.is_empty());
1452-
if !matches!(first_candidate.match_pairs[0].pattern.kind, PatKind::Or { .. }) {
1481+
if !matches!(first_candidate.match_pairs[0].test_case, TestCase::Or { .. }) {
14531482
self.test_candidates(
14541483
span,
14551484
scrutinee_span,
@@ -1463,7 +1492,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14631492

14641493
let match_pairs = mem::take(&mut first_candidate.match_pairs);
14651494
let (first_match_pair, remaining_match_pairs) = match_pairs.split_first().unwrap();
1466-
let PatKind::Or { ref pats } = &first_match_pair.pattern.kind else { unreachable!() };
1495+
let TestCase::Or { ref pats } = &first_match_pair.test_case else { unreachable!() };
14671496

14681497
let remainder_start = self.cfg.start_new_block();
14691498
let or_span = first_match_pair.pattern.span;
@@ -1474,7 +1503,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14741503
remainder_start,
14751504
pats,
14761505
or_span,
1477-
&first_match_pair.place,
14781506
fake_borrows,
14791507
);
14801508

@@ -1514,23 +1542,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15141542
}
15151543

15161544
#[instrument(
1517-
skip(self, start_block, otherwise_block, or_span, place, fake_borrows, candidate, pats),
1545+
skip(self, start_block, otherwise_block, or_span, fake_borrows, candidate, pats),
15181546
level = "debug"
15191547
)]
15201548
fn test_or_pattern<'pat>(
15211549
&mut self,
15221550
candidate: &mut Candidate<'pat, 'tcx>,
15231551
start_block: BasicBlock,
15241552
otherwise_block: BasicBlock,
1525-
pats: &'pat [Box<Pat<'tcx>>],
1553+
pats: &[FlatPat<'pat, 'tcx>],
15261554
or_span: Span,
1527-
place: &PlaceBuilder<'tcx>,
15281555
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
15291556
) {
15301557
debug!("candidate={:#?}\npats={:#?}", candidate, pats);
15311558
let mut or_candidates: Vec<_> = pats
15321559
.iter()
1533-
.map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard, self))
1560+
.cloned()
1561+
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard))
15341562
.collect();
15351563
let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect();
15361564
self.match_candidates(

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

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@
1212
//! sort of test: for example, testing which variant an enum is, or
1313
//! testing a value against a constant.
1414
15-
use crate::build::expr::as_place::PlaceBuilder;
16-
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair, TestCase};
15+
use crate::build::matches::{Ascription, Binding, Candidate, FlatPat, MatchPair, TestCase};
1716
use crate::build::Builder;
18-
use rustc_middle::thir::{Pat, PatKind};
1917

2018
use std::mem;
2119

@@ -100,26 +98,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10098
// Move or-patterns to the end, because they can result in us
10199
// creating additional candidates, so we want to test them as
102100
// late as possible.
103-
match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
101+
match_pairs.sort_by_key(|pair| matches!(pair.test_case, TestCase::Or { .. }));
104102
debug!(simplified = ?match_pairs, "simplify_match_pairs");
105103
}
106104

107105
/// Create a new candidate for each pattern in `pats`, and recursively simplify tje
108106
/// single-or-pattern case.
109107
pub(super) fn create_or_subcandidates<'pat>(
110108
&mut self,
111-
place: &PlaceBuilder<'tcx>,
112-
pats: &'pat [Box<Pat<'tcx>>],
109+
pats: &[FlatPat<'pat, 'tcx>],
113110
has_guard: bool,
114111
) -> Vec<Candidate<'pat, 'tcx>> {
115112
pats.iter()
116-
.map(|box pat| {
117-
let mut candidate = Candidate::new(place.clone(), pat, has_guard, self);
118-
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
113+
.cloned()
114+
.map(|flat_pat| {
115+
let mut candidate = Candidate::from_flat_pat(flat_pat, has_guard);
116+
if let [MatchPair { test_case: TestCase::Or { pats, .. }, .. }] =
119117
&*candidate.match_pairs
120118
{
121-
candidate.subcandidates =
122-
self.create_or_subcandidates(place, pats, candidate.has_guard);
119+
candidate.subcandidates = self.create_or_subcandidates(pats, has_guard);
123120
candidate.match_pairs.pop();
124121
}
125122
candidate

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
2-
use crate::build::matches::{MatchPair, TestCase};
2+
use crate::build::matches::{FlatPat, MatchPair, TestCase};
33
use crate::build::Builder;
44
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
55
use rustc_middle::mir::*;
@@ -121,7 +121,9 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
121121
let mut subpairs = Vec::new();
122122
let test_case = match pattern.kind {
123123
PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
124-
PatKind::Or { .. } => TestCase::Or,
124+
PatKind::Or { ref pats } => TestCase::Or {
125+
pats: pats.iter().map(|pat| FlatPat::new(place.clone(), pat, cx)).collect(),
126+
},
125127

126128
PatKind::Range(ref range) => {
127129
if range.is_full_range(cx.tcx) == Some(true) {

0 commit comments

Comments
 (0)