Skip to content

Commit 8c90218

Browse files
committed
merge guards early with metadata flags retention
1 parent 8a3fbab commit 8c90218

3 files changed

Lines changed: 39 additions & 38 deletions

File tree

compiler/rustc_mir_build/src/builder/matches/match_pair.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,12 @@ impl<'tcx> FlatPat<'tcx> {
8888
fn from_inter_pat(inter_pat: InterPat<'tcx>) -> Self {
8989
let mut match_pairs = vec![];
9090
let mut guard_patterns = vec![];
91-
if let Some(guard_pat) = inter_pat.guard_pat {
91+
if let Some(guard_pat) = inter_pat.guard {
9292
guard_patterns.push(super::OrderedPatternData::One(guard_pat));
9393
}
9494
let mut extra_data = PatternExtraData {
9595
span: inter_pat.pattern_span,
96-
guard_patterns,
96+
guards: guard_patterns,
9797
is_never: inter_pat.is_never,
9898
..Default::default()
9999
};
@@ -118,17 +118,14 @@ fn squash_inter_pat<'tcx>(
118118
or_subpats,
119119
ascriptions,
120120
binding,
121-
guard_pat,
121+
guard,
122122
pattern_span,
123123
is_never: _, // Not needed by `MatchPairTree` forests.
124124
} = inter_pat;
125125

126126
// Type ascriptions can appear regardless of whether the node is an or-pattern.
127127
extra_data.ascriptions.extend(ascriptions);
128-
129-
guard_pat.inspect(|&guard_pat| {
130-
extra_data.guard_patterns.push(super::OrderedPatternData::One(guard_pat));
131-
});
128+
guard.inspect(|&g| extra_data.guards.push(super::OrderedPatternData::One(g)));
132129

133130
// Or and non-or patterns have very different handling.
134131
if let Some(or_subpats) = or_subpats {
@@ -150,8 +147,9 @@ fn squash_inter_pat<'tcx>(
150147
// FIXME(@dianne): this needs updating/removing if we always merge or-patterns
151148
extra_data.bindings.push(super::OrderedPatternData::FromOrPattern);
152149
}
153-
if or_subpats.iter().any(|pat| !pat.extra_data.guard_patterns.is_empty()) {
154-
extra_data.guard_patterns.push(super::OrderedPatternData::FromOrPattern);
150+
151+
if or_subpats.iter().any(|pat| !pat.extra_data.guards.is_empty()) {
152+
extra_data.guards.push(super::OrderedPatternData::FromOrPattern);
155153
}
156154

157155
match_pairs.push(MatchPairTree {
@@ -226,7 +224,7 @@ struct InterPat<'tcx> {
226224
/// Binding to establish for a [`PatKind::Binding`] node.
227225
binding: Option<super::Binding<'tcx>>,
228226

229-
guard_pat: Option<ExprId>,
227+
guard: Option<ExprId>,
230228

231229
/// Span field of the THIR pattern this node was created from.
232230
pattern_span: Span,
@@ -270,7 +268,7 @@ impl<'tcx> InterPat<'tcx> {
270268
let mut or_subpats = None;
271269
let mut ascriptions = vec![];
272270
let mut binding = None;
273-
let mut guard_pat = None;
271+
let mut guard = None;
274272

275273
// Apply any type ascriptions to the value at `match_pair.place`.
276274
if let Some(place) = place
@@ -472,7 +470,7 @@ impl<'tcx> InterPat<'tcx> {
472470
PatKind::Guard { ref subpattern, condition } => {
473471
let subpattern = InterPat::lower_thir_pat(cx, place_builder, subpattern);
474472
subpats.push(subpattern);
475-
guard_pat = Some(condition);
473+
guard = Some(condition);
476474
None
477475
}
478476

@@ -496,7 +494,7 @@ impl<'tcx> InterPat<'tcx> {
496494
or_subpats,
497495
ascriptions,
498496
binding,
499-
guard_pat,
497+
guard,
500498
pattern_span: pattern.span,
501499
is_never,
502500
}

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

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -993,13 +993,13 @@ struct PatternExtraData<'tcx> {
993993
/// Whether this corresponds to a never pattern.
994994
is_never: bool,
995995

996-
/// [`ExprId`]s of subpattern conditions
997-
guard_patterns: Vec<OrderedPatternData<ExprId>>,
996+
/// [`ExprId`]s of guards that must be evaluated for this pattern
997+
guards: Vec<OrderedPatternData<ExprId>>,
998998
}
999999

10001000
impl<'tcx> PatternExtraData<'tcx> {
10011001
fn is_empty(&self) -> bool {
1002-
self.bindings.is_empty() && self.ascriptions.is_empty() && self.guard_patterns.is_empty()
1002+
self.bindings.is_empty() && self.ascriptions.is_empty() && self.guards.is_empty()
10031003
}
10041004
}
10051005

@@ -1087,8 +1087,12 @@ struct Candidate<'tcx> {
10871087
/// `otherwise_block`.
10881088
///
10891089
/// ---
1090-
/// For subcandidates, this is copied from the parent candidate
1091-
guards: Vec<ExprId>,
1090+
/// For subcandidates, this is copied from the parent candidate, so it indicates
1091+
/// whether the enclosing match arm has a guard.
1092+
under_guard: bool,
1093+
1094+
/// Whether subcandidates contain guards.
1095+
contains_guards: bool,
10921096

10931097
/// Holds extra pattern data that was prepared by [`FlatPat`], including bindings and
10941098
/// ascriptions that must be established if this candidate succeeds.
@@ -1125,20 +1129,24 @@ impl<'tcx> Candidate<'tcx> {
11251129
) -> Self {
11261130
// Use `FlatPat` to build simplified match pairs, then immediately
11271131
// incorporate them into a new candidate.
1128-
let flat_pat = FlatPat::new(place, pattern, cx);
1129-
let mut guards = Vec::new();
1132+
let mut flat_pat = FlatPat::new(place, pattern, cx);
1133+
let mut under_guard = false;
11301134
if let HasMatchGuard::Yes(g) = guard {
1131-
guards.push(g);
1135+
under_guard = true;
1136+
flat_pat.extra_data.guards.push(OrderedPatternData::One(g));
11321137
}
1133-
Self::from_flat_pat(flat_pat, guards)
1138+
Self::from_flat_pat(flat_pat, under_guard)
11341139
}
11351140

11361141
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
1137-
fn from_flat_pat(flat_pat: FlatPat<'tcx>, guards: Vec<ExprId>) -> Self {
1142+
fn from_flat_pat(flat_pat: FlatPat<'tcx>, under_guard: bool) -> Self {
1143+
let contains_guards = flat_pat.extra_data.guards.len() >= 2
1144+
|| flat_pat.extra_data.guards.len() == 1 && !under_guard;
11381145
let mut this = Candidate {
11391146
match_pairs: flat_pat.match_pairs,
11401147
extra_data: flat_pat.extra_data,
1141-
guards,
1148+
under_guard,
1149+
contains_guards,
11421150
subcandidates: Vec::new(),
11431151
or_span: None,
11441152
otherwise_block: None,
@@ -1494,12 +1502,9 @@ impl<'tcx> MatchTreeSubBranch<'tcx> {
14941502
.chain(candidate.extra_data.ascriptions)
14951503
.collect(),
14961504
guards: sub_branch_ordered_pat_data(
1497-
parent_data.iter().map(|parent| parent.guard_patterns.as_slice()),
1498-
&candidate.extra_data.guard_patterns,
1499-
)
1500-
.into_iter()
1501-
.chain(candidate.guards)
1502-
.collect(),
1505+
parent_data.iter().map(|parent| parent.guards.as_slice()),
1506+
&candidate.extra_data.guards,
1507+
),
15031508
is_never: candidate.extra_data.is_never,
15041509
}
15051510
}
@@ -1659,7 +1664,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16591664
Exhaustive::No => Some(otherwise_block),
16601665
};
16611666
for candidate in candidates.iter_mut().rev() {
1662-
let has_guard = !candidate.guards.is_empty();
1667+
let has_guard = candidate.under_guard || candidate.contains_guards;
16631668
candidate.visit_leaves_rev(|leaf_candidate| {
16641669
if let Some(next_candidate_start_block) = next_candidate_start_block {
16651670
let source_info = self.source_info(leaf_candidate.extra_data.span);
@@ -2004,10 +2009,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20042009
let TestableCase::Or { pats } = match_pair.testable_case else { bug!() };
20052010
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
20062011
candidate.or_span = Some(match_pair.pattern_span);
2007-
candidate.subcandidates = pats
2008-
.into_iter()
2009-
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.guards.clone()))
2010-
.collect();
2012+
candidate.subcandidates =
2013+
pats.into_iter().map(|flat_pat| Candidate::from_flat_pat(flat_pat, false)).collect();
20112014
candidate.subcandidates[0].false_edge_start_block = candidate.false_edge_start_block;
20122015
}
20132016

@@ -2070,7 +2073,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20702073
/// in match tree lowering.
20712074
fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) {
20722075
assert!(!candidate.subcandidates.is_empty());
2073-
if !candidate.guards.is_empty() || !candidate.extra_data.guard_patterns.is_empty() {
2076+
if candidate.under_guard || candidate.contains_guards {
20742077
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
20752078
return;
20762079
}
@@ -2190,7 +2193,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21902193
// directly to `last_otherwise`. If there is a guard,
21912194
// `leaf_candidate.otherwise_block` can be reached by guard failure as well, so we
21922195
// can't skip `Q`.
2193-
let or_otherwise = if !leaf_candidate.guards.is_empty() {
2196+
let or_otherwise = if leaf_candidate.under_guard {
21942197
leaf_candidate.otherwise_block.unwrap()
21952198
} else {
21962199
last_otherwise.unwrap()

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub(super) fn collect_fake_borrows<'tcx>(
7272
temp_span: Span,
7373
scrutinee_base: PlaceBase,
7474
) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
75-
if candidates.iter().all(|candidate| candidate.guards.is_empty()) {
75+
if !candidates.iter().any(|candidate| candidate.under_guard || candidate.contains_guards) {
7676
// Fake borrows are only used when there is a guard.
7777
return Vec::new();
7878
}

0 commit comments

Comments
 (0)