Skip to content

Commit 5902d4e

Browse files
authored
Rollup merge of rust-lang#122221 - Nadrieril:patextradata, r=oli-obk
match lowering: define a convenient struct Small refactor PR: `bindings` and `ascriptions` always come together so I made a struct for them. I'll have one or two fields to add to it in a later PR as well.
2 parents 3a5abff + 594cf1d commit 5902d4e

File tree

3 files changed

+67
-72
lines changed

3 files changed

+67
-72
lines changed

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

+59-59
Original file line numberDiff line numberDiff line change
@@ -506,13 +506,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
506506
traverse_candidate(
507507
candidate,
508508
&mut Vec::new(),
509-
&mut |leaf_candidate, parent_bindings| {
509+
&mut |leaf_candidate, parent_data| {
510510
if let Some(arm) = arm {
511511
self.clear_top_scope(arm.scope);
512512
}
513513
let binding_end = self.bind_and_guard_matched_candidate(
514514
leaf_candidate,
515-
parent_bindings,
515+
parent_data,
516516
fake_borrow_temps,
517517
scrutinee_span,
518518
arm_match_scope,
@@ -524,12 +524,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
524524
}
525525
self.cfg.goto(binding_end, outer_source_info, target_block);
526526
},
527-
|inner_candidate, parent_bindings| {
528-
parent_bindings.push((inner_candidate.bindings, inner_candidate.ascriptions));
527+
|inner_candidate, parent_data| {
528+
parent_data.push(inner_candidate.extra_data);
529529
inner_candidate.subcandidates.into_iter()
530530
},
531-
|parent_bindings| {
532-
parent_bindings.pop();
531+
|parent_data| {
532+
parent_data.pop();
533533
},
534534
);
535535

@@ -651,7 +651,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
651651
if set_match_place {
652652
let mut next = Some(&candidate);
653653
while let Some(candidate_ref) = next.take() {
654-
for binding in &candidate_ref.bindings {
654+
for binding in &candidate_ref.extra_data.bindings {
655655
let local = self.var_local_id(binding.var_id, OutsideGuard);
656656
// `try_to_place` may fail if it is unable to resolve the given
657657
// `PlaceBuilder` inside a closure. In this case, we don't want to include
@@ -924,22 +924,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
924924
}
925925
}
926926

927-
/// A pattern in a form suitable for generating code.
927+
/// Data extracted from a pattern that doesn't affect which branch is taken. Collected during
928+
/// pattern simplification and not mutated later.
928929
#[derive(Debug, Clone)]
929-
struct FlatPat<'pat, 'tcx> {
930+
struct PatternExtraData<'tcx> {
930931
/// [`Span`] of the original pattern.
931932
span: Span,
932933

934+
/// Bindings that must be established.
935+
bindings: Vec<Binding<'tcx>>,
936+
937+
/// Types that must be asserted.
938+
ascriptions: Vec<Ascription<'tcx>>,
939+
}
940+
941+
impl<'tcx> PatternExtraData<'tcx> {
942+
fn is_empty(&self) -> bool {
943+
self.bindings.is_empty() && self.ascriptions.is_empty()
944+
}
945+
}
946+
947+
/// A pattern in a form suitable for generating code.
948+
#[derive(Debug, Clone)]
949+
struct FlatPat<'pat, 'tcx> {
933950
/// To match the pattern, all of these must be satisfied...
934951
// Invariant: all the `MatchPair`s are recursively simplified.
935952
// Invariant: or-patterns must be sorted to the end.
936953
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
937954

938-
/// ...these bindings established...
939-
bindings: Vec<Binding<'tcx>>,
940-
941-
/// ...and these types asserted.
942-
ascriptions: Vec<Ascription<'tcx>>,
955+
extra_data: PatternExtraData<'tcx>,
943956
}
944957

945958
impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
@@ -948,43 +961,38 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
948961
pattern: &'pat Pat<'tcx>,
949962
cx: &mut Builder<'_, 'tcx>,
950963
) -> Self {
951-
let mut match_pairs = vec![MatchPair::new(place, pattern, cx)];
952-
let mut bindings = Vec::new();
953-
let mut ascriptions = Vec::new();
954-
955-
cx.simplify_match_pairs(&mut match_pairs, &mut bindings, &mut ascriptions);
956-
957-
FlatPat { span: pattern.span, match_pairs, bindings, ascriptions }
964+
let mut flat_pat = FlatPat {
965+
match_pairs: vec![MatchPair::new(place, pattern, cx)],
966+
extra_data: PatternExtraData {
967+
span: pattern.span,
968+
bindings: Vec::new(),
969+
ascriptions: Vec::new(),
970+
},
971+
};
972+
cx.simplify_match_pairs(&mut flat_pat.match_pairs, &mut flat_pat.extra_data);
973+
flat_pat
958974
}
959975
}
960976

961977
#[derive(Debug)]
962978
struct Candidate<'pat, 'tcx> {
963-
/// [`Span`] of the original pattern that gave rise to this candidate.
964-
span: Span,
965-
966-
/// Whether this `Candidate` has a guard.
967-
has_guard: bool,
968-
969-
/// All of these must be satisfied...
979+
/// For the candidate to match, all of these must be satisfied...
970980
// Invariant: all the `MatchPair`s are recursively simplified.
971981
// Invariant: or-patterns must be sorted at the end.
972982
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
973983

974-
/// ...these bindings established...
975-
// Invariant: not mutated after candidate creation.
976-
bindings: Vec<Binding<'tcx>>,
977-
978-
/// ...and these types asserted...
979-
// Invariant: not mutated after candidate creation.
980-
ascriptions: Vec<Ascription<'tcx>>,
981-
982984
/// ...and if this is non-empty, one of these subcandidates also has to match...
983985
subcandidates: Vec<Candidate<'pat, 'tcx>>,
984986

985-
/// ...and the guard must be evaluated; if it's `false` then branch to `otherwise_block`.
987+
/// ...and the guard must be evaluated if there is one.
988+
has_guard: bool,
989+
990+
/// If the guard is `false` then branch to `otherwise_block`.
986991
otherwise_block: Option<BasicBlock>,
987992

993+
/// If the candidate matches, bindings and ascriptions must be established.
994+
extra_data: PatternExtraData<'tcx>,
995+
988996
/// The block before the `bindings` have been established.
989997
pre_binding_block: Option<BasicBlock>,
990998
/// The pre-binding block of the next candidate.
@@ -1003,10 +1011,8 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
10031011

10041012
fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
10051013
Candidate {
1006-
span: flat_pat.span,
10071014
match_pairs: flat_pat.match_pairs,
1008-
bindings: flat_pat.bindings,
1009-
ascriptions: flat_pat.ascriptions,
1015+
extra_data: flat_pat.extra_data,
10101016
has_guard,
10111017
subcandidates: Vec::new(),
10121018
otherwise_block: None,
@@ -1518,9 +1524,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15181524
self.merge_trivial_subcandidates(subcandidate, source_info);
15191525

15201526
// FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
1521-
can_merge &= subcandidate.subcandidates.is_empty()
1522-
&& subcandidate.bindings.is_empty()
1523-
&& subcandidate.ascriptions.is_empty();
1527+
can_merge &=
1528+
subcandidate.subcandidates.is_empty() && subcandidate.extra_data.is_empty();
15241529
}
15251530

15261531
if can_merge {
@@ -1943,7 +1948,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19431948
fn bind_and_guard_matched_candidate<'pat>(
19441949
&mut self,
19451950
candidate: Candidate<'pat, 'tcx>,
1946-
parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
1951+
parent_data: &[PatternExtraData<'tcx>],
19471952
fake_borrows: &[(Place<'tcx>, Local)],
19481953
scrutinee_span: Span,
19491954
arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
@@ -1954,7 +1959,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19541959

19551960
debug_assert!(candidate.match_pairs.is_empty());
19561961

1957-
let candidate_source_info = self.source_info(candidate.span);
1962+
let candidate_source_info = self.source_info(candidate.extra_data.span);
19581963

19591964
let mut block = candidate.pre_binding_block.unwrap();
19601965

@@ -1971,11 +1976,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19711976

19721977
self.ascribe_types(
19731978
block,
1974-
parent_bindings
1979+
parent_data
19751980
.iter()
1976-
.flat_map(|(_, ascriptions)| ascriptions)
1981+
.flat_map(|d| &d.ascriptions)
19771982
.cloned()
1978-
.chain(candidate.ascriptions),
1983+
.chain(candidate.extra_data.ascriptions),
19791984
);
19801985

19811986
// rust-lang/rust#27282: The `autoref` business deserves some
@@ -2063,10 +2068,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20632068
&& let Some(guard) = arm.guard
20642069
{
20652070
let tcx = self.tcx;
2066-
let bindings = parent_bindings
2067-
.iter()
2068-
.flat_map(|(bindings, _)| bindings)
2069-
.chain(&candidate.bindings);
2071+
let bindings =
2072+
parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings);
20702073

20712074
self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone());
20722075
let guard_frame = GuardFrame {
@@ -2144,10 +2147,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21442147
// ```
21452148
//
21462149
// and that is clearly not correct.
2147-
let by_value_bindings = parent_bindings
2150+
let by_value_bindings = parent_data
21482151
.iter()
2149-
.flat_map(|(bindings, _)| bindings)
2150-
.chain(&candidate.bindings)
2152+
.flat_map(|d| &d.bindings)
2153+
.chain(&candidate.extra_data.bindings)
21512154
.filter(|binding| matches!(binding.binding_mode, BindingMode::ByValue));
21522155
// Read all of the by reference bindings to ensure that the
21532156
// place they refer to can't be modified by the guard.
@@ -2172,10 +2175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21722175
self.bind_matched_candidate_for_arm_body(
21732176
block,
21742177
schedule_drops,
2175-
parent_bindings
2176-
.iter()
2177-
.flat_map(|(bindings, _)| bindings)
2178-
.chain(&candidate.bindings),
2178+
parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings),
21792179
storages_alive,
21802180
);
21812181
block

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

+6-11
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,19 @@
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::matches::{Ascription, Binding, Candidate, FlatPat, MatchPair, TestCase};
15+
use crate::build::matches::{Candidate, FlatPat, MatchPair, PatternExtraData, TestCase};
1616
use crate::build::Builder;
1717

1818
use std::mem;
1919

2020
impl<'a, 'tcx> Builder<'a, 'tcx> {
2121
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
22-
/// ascriptions in the provided `Vec`s.
22+
/// ascriptions in `extra_data`.
2323
#[instrument(skip(self), level = "debug")]
2424
pub(super) fn simplify_match_pairs<'pat>(
2525
&mut self,
2626
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
27-
candidate_bindings: &mut Vec<Binding<'tcx>>,
28-
candidate_ascriptions: &mut Vec<Ascription<'tcx>>,
27+
extra_data: &mut PatternExtraData<'tcx>,
2928
) {
3029
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
3130
// bindings in `pat` before `x`. E.g. (#69971):
@@ -45,17 +44,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4544
// after any bindings in `pat`. This doesn't work for or-patterns: the current structure of
4645
// match lowering forces us to lower bindings inside or-patterns last.
4746
for mut match_pair in mem::take(match_pairs) {
48-
self.simplify_match_pairs(
49-
&mut match_pair.subpairs,
50-
candidate_bindings,
51-
candidate_ascriptions,
52-
);
47+
self.simplify_match_pairs(&mut match_pair.subpairs, extra_data);
5348
if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
5449
if let Some(binding) = binding {
55-
candidate_bindings.push(binding);
50+
extra_data.bindings.push(binding);
5651
}
5752
if let Some(ascription) = ascription {
58-
candidate_ascriptions.push(ascription);
53+
extra_data.ascriptions.push(ascription);
5954
}
6055
// Simplifiable pattern; we replace it with its already simplified subpairs.
6156
match_pairs.append(&mut match_pair.subpairs);

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
280280
}
281281

282282
fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
283-
for binding in &candidate.bindings {
283+
for binding in &candidate.extra_data.bindings {
284284
self.visit_binding(binding);
285285
}
286286
for match_pair in &candidate.match_pairs {
@@ -289,7 +289,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
289289
}
290290

291291
fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
292-
for binding in &flat_pat.bindings {
292+
for binding in &flat_pat.extra_data.bindings {
293293
self.visit_binding(binding);
294294
}
295295
for match_pair in &flat_pat.match_pairs {

0 commit comments

Comments
 (0)