Skip to content

Commit 65ad1b8

Browse files
committed
Eagerly simplify
1 parent 8c1b720 commit 65ad1b8

File tree

4 files changed

+53
-95
lines changed

4 files changed

+53
-95
lines changed

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

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -974,9 +974,9 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
974974
place: PlaceBuilder<'tcx>,
975975
pattern: &'pat Pat<'tcx>,
976976
has_guard: bool,
977-
cx: &Builder<'_, 'tcx>,
977+
cx: &mut Builder<'_, 'tcx>,
978978
) -> Self {
979-
Candidate {
979+
let mut candidate = Candidate {
980980
span: pattern.span,
981981
has_guard,
982982
match_pairs: vec![MatchPair::new(place, pattern, cx)],
@@ -986,7 +986,15 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
986986
otherwise_block: None,
987987
pre_binding_block: None,
988988
next_candidate_pre_binding_block: None,
989-
}
989+
};
990+
991+
cx.simplify_candidate(
992+
&mut candidate.bindings,
993+
&mut candidate.ascriptions,
994+
&mut candidate.match_pairs,
995+
);
996+
997+
candidate
990998
}
991999

9921000
/// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1042,13 +1050,16 @@ struct Ascription<'tcx> {
10421050
variance: ty::Variance,
10431051
}
10441052

1045-
#[derive(Clone, Debug)]
1053+
#[derive(Debug)]
10461054
pub(crate) struct MatchPair<'pat, 'tcx> {
1047-
// this place...
1055+
// This place...
10481056
place: PlaceBuilder<'tcx>,
10491057

10501058
// ... must match this pattern.
10511059
pattern: &'pat Pat<'tcx>,
1060+
1061+
/// Precomputed sub-match pairs.
1062+
subpairs: Vec<Self>,
10521063
}
10531064

10541065
/// See [`Test`] for more.
@@ -1170,12 +1181,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11701181
// be a switch or pattern comparison.
11711182
let mut split_or_candidate = false;
11721183
for candidate in &mut *candidates {
1173-
self.simplify_candidate(
1174-
&mut candidate.bindings,
1175-
&mut candidate.ascriptions,
1176-
&mut candidate.match_pairs,
1177-
);
1178-
11791184
split_or_candidate |= {
11801185
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
11811186
&*candidate.match_pairs

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use crate::build::expr::as_place::PlaceBuilder;
1616
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair};
1717
use crate::build::Builder;
18+
use rustc_middle::mir::PlaceElem;
1819
use rustc_middle::thir::{self, *};
1920
use std::mem;
2021

@@ -119,12 +120,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
119120
pats.iter()
120121
.map(|box pat| {
121122
let mut candidate = Candidate::new(place.clone(), pat, has_guard, self);
122-
self.simplify_candidate(
123-
&mut candidate.bindings,
124-
&mut candidate.ascriptions,
125-
&mut candidate.match_pairs,
126-
);
127-
128123
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place, .. }] =
129124
&*candidate.match_pairs
130125
{
@@ -144,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
144139
/// candidate.
145140
fn simplify_match_pair<'pat>(
146141
&mut self,
147-
match_pair: MatchPair<'pat, 'tcx>,
142+
mut match_pair: MatchPair<'pat, 'tcx>,
148143
bindings: &mut Vec<Binding<'tcx>>,
149144
ascriptions: &mut Vec<Ascription<'tcx>>,
150145
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
@@ -230,6 +225,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
230225
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
231226
Ok(())
232227
} else {
228+
self.prefix_slice_suffix(
229+
&mut match_pair.subpairs,
230+
&match_pair.place,
231+
prefix,
232+
slice,
233+
suffix,
234+
);
235+
self.simplify_candidate(bindings, ascriptions, &mut match_pair.subpairs);
233236
Err(match_pair)
234237
}
235238
}
@@ -250,6 +253,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
250253
match_pairs.extend(self.field_match_pairs(place_builder, subpatterns));
251254
Ok(())
252255
} else {
256+
// If we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
257+
// we want to create a set of derived match-patterns like
258+
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
259+
let downcast_place = match_pair.place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
260+
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
261+
// e.g., `(x as Variant).0`
262+
let place = downcast_place.clone_project(PlaceElem::Field(
263+
subpattern.field,
264+
subpattern.pattern.ty,
265+
));
266+
// e.g., `(x as Variant).0 @ P1`
267+
MatchPair::new(place, &subpattern.pattern, self)
268+
});
269+
270+
match_pair.subpairs.extend(consequent_match_pairs);
271+
self.simplify_candidate(bindings, ascriptions, &mut match_pair.subpairs);
253272
Err(match_pair)
254273
}
255274
}

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

Lines changed: 10 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -595,16 +595,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
595595
// informs variant patterns, but nothing else.
596596
(
597597
&TestKind::Switch { adt_def: tested_adt_def, .. },
598-
&PatKind::Variant { adt_def, variant_index, ref subpatterns, .. },
598+
&PatKind::Variant { adt_def, variant_index, .. },
599599
) => {
600600
assert_eq!(adt_def, tested_adt_def);
601-
self.candidate_after_variant_switch(
602-
match_pair_index,
603-
adt_def,
604-
variant_index,
605-
subpatterns,
606-
candidate,
607-
);
601+
let match_pair = candidate.match_pairs.remove(match_pair_index);
602+
candidate.match_pairs.extend(match_pair.subpairs);
608603
Some(variant_index.as_usize())
609604
}
610605

@@ -619,7 +614,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
619614
if is_switch_ty(match_pair.pattern.ty) =>
620615
{
621616
let index = options.get_index_of(value).unwrap();
622-
self.candidate_without_match_pair(match_pair_index, candidate);
617+
candidate.match_pairs.remove(match_pair_index);
623618
Some(index)
624619
}
625620

@@ -645,13 +640,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
645640
(Ordering::Equal, &None) => {
646641
// on true, min_len = len = $actual_length,
647642
// on false, len != $actual_length
648-
self.candidate_after_slice_test(
649-
match_pair_index,
650-
candidate,
651-
prefix,
652-
slice,
653-
suffix,
654-
);
643+
let match_pair = candidate.match_pairs.remove(match_pair_index);
644+
candidate.match_pairs.extend(match_pair.subpairs);
655645
Some(0)
656646
}
657647
(Ordering::Less, _) => {
@@ -683,13 +673,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
683673
(Ordering::Equal, &Some(_)) => {
684674
// $actual_len >= test_len = pat_len,
685675
// so we can match.
686-
self.candidate_after_slice_test(
687-
match_pair_index,
688-
candidate,
689-
prefix,
690-
slice,
691-
suffix,
692-
);
676+
let match_pair = candidate.match_pairs.remove(match_pair_index);
677+
candidate.match_pairs.extend(match_pair.subpairs);
693678
Some(0)
694679
}
695680
(Ordering::Less, _) | (Ordering::Equal, &None) => {
@@ -713,7 +698,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
713698

714699
(TestKind::Range(test), PatKind::Range(pat)) => {
715700
if test == pat {
716-
self.candidate_without_match_pair(match_pair_index, candidate);
701+
candidate.match_pairs.remove(match_pair_index);
717702
return Some(0);
718703
}
719704

@@ -751,7 +736,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
751736
// FIXME(#29623) we can be more clever here
752737
let pattern_test = self.test(match_pair);
753738
if pattern_test.kind == test.kind {
754-
self.candidate_without_match_pair(match_pair_index, candidate);
739+
candidate.match_pairs.remove(match_pair_index);
755740
Some(0)
756741
} else {
757742
None
@@ -760,57 +745,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
760745
}
761746
}
762747

763-
fn candidate_without_match_pair(
764-
&mut self,
765-
match_pair_index: usize,
766-
candidate: &mut Candidate<'_, 'tcx>,
767-
) {
768-
candidate.match_pairs.remove(match_pair_index);
769-
}
770-
771-
fn candidate_after_slice_test<'pat>(
772-
&mut self,
773-
match_pair_index: usize,
774-
candidate: &mut Candidate<'pat, 'tcx>,
775-
prefix: &'pat [Box<Pat<'tcx>>],
776-
opt_slice: &'pat Option<Box<Pat<'tcx>>>,
777-
suffix: &'pat [Box<Pat<'tcx>>],
778-
) {
779-
let removed_place = candidate.match_pairs.remove(match_pair_index).place;
780-
self.prefix_slice_suffix(
781-
&mut candidate.match_pairs,
782-
&removed_place,
783-
prefix,
784-
opt_slice,
785-
suffix,
786-
);
787-
}
788-
789-
fn candidate_after_variant_switch<'pat>(
790-
&mut self,
791-
match_pair_index: usize,
792-
adt_def: ty::AdtDef<'tcx>,
793-
variant_index: VariantIdx,
794-
subpatterns: &'pat [FieldPat<'tcx>],
795-
candidate: &mut Candidate<'pat, 'tcx>,
796-
) {
797-
let match_pair = candidate.match_pairs.remove(match_pair_index);
798-
799-
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
800-
// we want to create a set of derived match-patterns like
801-
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
802-
let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
803-
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
804-
// e.g., `(x as Variant).0`
805-
let place = downcast_place
806-
.clone_project(PlaceElem::Field(subpattern.field, subpattern.pattern.ty));
807-
// e.g., `(x as Variant).0 @ P1`
808-
MatchPair::new(place, &subpattern.pattern, self)
809-
});
810-
811-
candidate.match_pairs.extend(consequent_match_pairs);
812-
}
813-
814748
fn error_simplifiable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
815749
span_bug!(match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern)
816750
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,6 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
116116
if may_need_cast {
117117
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
118118
}
119-
MatchPair { place, pattern }
119+
MatchPair { place, pattern, subpairs: Vec::new() }
120120
}
121121
}

0 commit comments

Comments
 (0)