@@ -506,13 +506,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
506
506
traverse_candidate(
507
507
candidate,
508
508
&mut Vec::new(),
509
- &mut |leaf_candidate, parent_bindings | {
509
+ &mut |leaf_candidate, parent_data | {
510
510
if let Some(arm) = arm {
511
511
self.clear_top_scope(arm.scope);
512
512
}
513
513
let binding_end = self.bind_and_guard_matched_candidate(
514
514
leaf_candidate,
515
- parent_bindings ,
515
+ parent_data ,
516
516
fake_borrow_temps,
517
517
scrutinee_span,
518
518
arm_match_scope,
@@ -524,12 +524,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
524
524
}
525
525
self.cfg.goto(binding_end, outer_source_info, target_block);
526
526
},
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 );
529
529
inner_candidate.subcandidates.into_iter()
530
530
},
531
- |parent_bindings | {
532
- parent_bindings .pop();
531
+ |parent_data | {
532
+ parent_data .pop();
533
533
},
534
534
);
535
535
@@ -651,7 +651,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
651
651
if set_match_place {
652
652
let mut next = Some(&candidate);
653
653
while let Some(candidate_ref) = next.take() {
654
- for binding in &candidate_ref.bindings {
654
+ for binding in &candidate_ref.extra_data. bindings {
655
655
let local = self.var_local_id(binding.var_id, OutsideGuard);
656
656
// `try_to_place` may fail if it is unable to resolve the given
657
657
// `PlaceBuilder` inside a closure. In this case, we don't want to include
@@ -924,22 +924,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
924
924
}
925
925
}
926
926
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.
928
929
#[derive(Debug, Clone)]
929
- struct FlatPat<'pat, 'tcx> {
930
+ struct PatternExtraData< 'tcx> {
930
931
/// [`Span`] of the original pattern.
931
932
span: Span,
932
933
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> {
933
950
/// To match the pattern, all of these must be satisfied...
934
951
// Invariant: all the `MatchPair`s are recursively simplified.
935
952
// Invariant: or-patterns must be sorted to the end.
936
953
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
937
954
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>,
943
956
}
944
957
945
958
impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
@@ -948,43 +961,38 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
948
961
pattern: &'pat Pat<'tcx>,
949
962
cx: &mut Builder<'_, 'tcx>,
950
963
) -> 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
958
974
}
959
975
}
960
976
961
977
#[derive(Debug)]
962
978
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...
970
980
// Invariant: all the `MatchPair`s are recursively simplified.
971
981
// Invariant: or-patterns must be sorted at the end.
972
982
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
973
983
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
-
982
984
/// ...and if this is non-empty, one of these subcandidates also has to match...
983
985
subcandidates: Vec<Candidate<'pat, 'tcx>>,
984
986
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`.
986
991
otherwise_block: Option<BasicBlock>,
987
992
993
+ /// If the candidate matches, bindings and ascriptions must be established.
994
+ extra_data: PatternExtraData<'tcx>,
995
+
988
996
/// The block before the `bindings` have been established.
989
997
pre_binding_block: Option<BasicBlock>,
990
998
/// The pre-binding block of the next candidate.
@@ -1003,10 +1011,8 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
1003
1011
1004
1012
fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
1005
1013
Candidate {
1006
- span: flat_pat.span,
1007
1014
match_pairs: flat_pat.match_pairs,
1008
- bindings: flat_pat.bindings,
1009
- ascriptions: flat_pat.ascriptions,
1015
+ extra_data: flat_pat.extra_data,
1010
1016
has_guard,
1011
1017
subcandidates: Vec::new(),
1012
1018
otherwise_block: None,
@@ -1518,9 +1524,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1518
1524
self.merge_trivial_subcandidates(subcandidate, source_info);
1519
1525
1520
1526
// 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();
1524
1529
}
1525
1530
1526
1531
if can_merge {
@@ -1943,7 +1948,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1943
1948
fn bind_and_guard_matched_candidate<'pat>(
1944
1949
&mut self,
1945
1950
candidate: Candidate<'pat, 'tcx>,
1946
- parent_bindings : &[(Vec<Binding< 'tcx>>, Vec<Ascription<'tcx>>) ],
1951
+ parent_data : &[PatternExtraData< 'tcx>],
1947
1952
fake_borrows: &[(Place<'tcx>, Local)],
1948
1953
scrutinee_span: Span,
1949
1954
arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
@@ -1954,7 +1959,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1954
1959
1955
1960
debug_assert!(candidate.match_pairs.is_empty());
1956
1961
1957
- let candidate_source_info = self.source_info(candidate.span);
1962
+ let candidate_source_info = self.source_info(candidate.extra_data. span);
1958
1963
1959
1964
let mut block = candidate.pre_binding_block.unwrap();
1960
1965
@@ -1971,11 +1976,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1971
1976
1972
1977
self.ascribe_types(
1973
1978
block,
1974
- parent_bindings
1979
+ parent_data
1975
1980
.iter()
1976
- .flat_map(|(_, ascriptions)| ascriptions)
1981
+ .flat_map(|d| &d. ascriptions)
1977
1982
.cloned()
1978
- .chain(candidate.ascriptions),
1983
+ .chain(candidate.extra_data. ascriptions),
1979
1984
);
1980
1985
1981
1986
// rust-lang/rust#27282: The `autoref` business deserves some
@@ -2063,10 +2068,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2063
2068
&& let Some(guard) = arm.guard
2064
2069
{
2065
2070
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);
2070
2073
2071
2074
self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone());
2072
2075
let guard_frame = GuardFrame {
@@ -2144,10 +2147,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2144
2147
// ```
2145
2148
//
2146
2149
// and that is clearly not correct.
2147
- let by_value_bindings = parent_bindings
2150
+ let by_value_bindings = parent_data
2148
2151
.iter()
2149
- .flat_map(|(bindings, _)| bindings)
2150
- .chain(&candidate.bindings)
2152
+ .flat_map(|d| &d. bindings)
2153
+ .chain(&candidate.extra_data. bindings)
2151
2154
.filter(|binding| matches!(binding.binding_mode, BindingMode::ByValue));
2152
2155
// Read all of the by reference bindings to ensure that the
2153
2156
// place they refer to can't be modified by the guard.
@@ -2172,10 +2175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2172
2175
self.bind_matched_candidate_for_arm_body(
2173
2176
block,
2174
2177
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),
2179
2179
storages_alive,
2180
2180
);
2181
2181
block
0 commit comments