Skip to content

Commit d33fbc9

Browse files
committed
Compute subpairs when creating match pair
1 parent f9115b1 commit d33fbc9

File tree

2 files changed

+72
-78
lines changed

2 files changed

+72
-78
lines changed

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

+25-76
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
131131
ascriptions: &mut Vec<Ascription<'tcx>>,
132132
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
133133
) -> Result<(), MatchPair<'pat, 'tcx>> {
134-
assert!(match_pair.subpairs.is_empty(), "mustn't simplify a match pair twice");
135134
match match_pair.pattern.kind {
135+
PatKind::Leaf { .. }
136+
| PatKind::Deref { .. }
137+
| PatKind::Array { .. }
138+
| PatKind::Never
139+
| PatKind::Wild
140+
| PatKind::Error(_) => {}
141+
136142
PatKind::AscribeUserType {
137-
ref subpattern,
138143
ascription: thir::Ascription { ref annotation, variance },
144+
..
139145
} => {
140146
// Apply the type ascription to the value at `match_pair.place`
141147
if let Some(source) = match_pair.place.try_to_place(self) {
@@ -145,15 +151,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
145151
variance,
146152
});
147153
}
148-
149-
match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
150-
151-
Ok(())
152-
}
153-
154-
PatKind::Wild | PatKind::Error(_) => {
155-
// nothing left to do
156-
Ok(())
157154
}
158155

159156
PatKind::Binding {
@@ -162,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
162159
mode,
163160
var,
164161
ty: _,
165-
ref subpattern,
162+
subpattern: _,
166163
is_primary: _,
167164
} => {
168165
if let Some(source) = match_pair.place.try_to_place(self) {
@@ -173,24 +170,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
173170
binding_mode: mode,
174171
});
175172
}
176-
177-
if let Some(subpattern) = subpattern.as_ref() {
178-
// this is the `x @ P` case; have to keep matching against `P` now
179-
match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
180-
}
181-
182-
Ok(())
183-
}
184-
185-
PatKind::Never => {
186-
// A never pattern acts like a load from the place.
187-
// FIXME(never_patterns): load from the place
188-
Ok(())
189-
}
190-
191-
PatKind::Constant { .. } => {
192-
// FIXME normalize patterns when possible
193-
Err(match_pair)
194173
}
195174

196175
PatKind::InlineConstant { subpattern: ref pattern, def } => {
@@ -225,38 +204,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
225204
variance: ty::Contravariant,
226205
});
227206
}
228-
match_pairs.push(MatchPair::new(match_pair.place, pattern, self));
207+
}
229208

230-
Ok(())
209+
PatKind::Constant { .. } => {
210+
// FIXME normalize patterns when possible
211+
return Err(match_pair);
231212
}
232213

233214
PatKind::Range(ref range) => {
234-
if let Some(true) = range.is_full_range(self.tcx) {
235-
// Irrefutable pattern match.
236-
return Ok(());
215+
if range.is_full_range(self.tcx) != Some(true) {
216+
return Err(match_pair);
237217
}
238-
Err(match_pair)
239218
}
240219

241220
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
242-
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
243-
// irrefutable
244-
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
245-
Ok(())
246-
} else {
247-
self.prefix_slice_suffix(
248-
&mut match_pair.subpairs,
249-
&match_pair.place,
250-
prefix,
251-
slice,
252-
suffix,
253-
);
221+
if !(prefix.is_empty() && slice.is_some() && suffix.is_empty()) {
254222
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
255-
Err(match_pair)
223+
return Err(match_pair);
256224
}
257225
}
258226

259-
PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => {
227+
PatKind::Variant { adt_def, args, variant_index, subpatterns: _ } => {
260228
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
261229
i == variant_index || {
262230
(self.tcx.features().exhaustive_patterns
@@ -268,36 +236,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
268236
}
269237
}) && (adt_def.did().is_local()
270238
|| !adt_def.is_variant_list_non_exhaustive());
271-
if irrefutable {
272-
let place_builder = match_pair.place.downcast(adt_def, variant_index);
273-
match_pairs.extend(self.field_match_pairs(place_builder, subpatterns));
274-
Ok(())
275-
} else {
276-
let downcast_place = match_pair.place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
277-
match_pair.subpairs = self.field_match_pairs(downcast_place, subpatterns);
239+
if !irrefutable {
278240
self.simplify_match_pairs(&mut match_pair.subpairs, bindings, ascriptions);
279-
Err(match_pair)
241+
return Err(match_pair);
280242
}
281243
}
282244

283-
PatKind::Array { ref prefix, ref slice, ref suffix } => {
284-
self.prefix_slice_suffix(match_pairs, &match_pair.place, prefix, slice, suffix);
285-
Ok(())
286-
}
287-
288-
PatKind::Leaf { ref subpatterns } => {
289-
// tuple struct, match subpats (if any)
290-
match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns));
291-
Ok(())
292-
}
293-
294-
PatKind::Deref { ref subpattern } => {
295-
let place_builder = match_pair.place.deref();
296-
match_pairs.push(MatchPair::new(place_builder, subpattern, self));
297-
Ok(())
298-
}
299-
300-
PatKind::Or { .. } => Err(match_pair),
245+
PatKind::Or { .. } => return Err(match_pair),
301246
}
247+
248+
// Simplifiable pattern; we replace it with its subpairs.
249+
match_pairs.append(&mut match_pair.subpairs);
250+
Ok(())
302251
}
303252
}

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

+47-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
9696
pub(in crate::build) fn new(
9797
mut place: PlaceBuilder<'tcx>,
9898
pattern: &'pat Pat<'tcx>,
99-
cx: &Builder<'_, 'tcx>,
99+
cx: &mut Builder<'_, 'tcx>,
100100
) -> MatchPair<'pat, 'tcx> {
101101
// Force the place type to the pattern's type.
102102
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
@@ -116,6 +116,51 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
116116
if may_need_cast {
117117
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
118118
}
119-
MatchPair { place, pattern, subpairs: Vec::new() }
119+
120+
let mut subpairs = Vec::new();
121+
match pattern.kind {
122+
PatKind::Constant { .. }
123+
| PatKind::Range(_)
124+
| PatKind::Or { .. }
125+
| PatKind::Never
126+
| PatKind::Wild
127+
| PatKind::Error(_) => {}
128+
129+
PatKind::AscribeUserType { ref subpattern, .. } => {
130+
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
131+
}
132+
133+
PatKind::Binding { ref subpattern, .. } => {
134+
if let Some(subpattern) = subpattern.as_ref() {
135+
// this is the `x @ P` case; have to keep matching against `P` now
136+
subpairs.push(MatchPair::new(place.clone(), subpattern, cx));
137+
}
138+
}
139+
140+
PatKind::InlineConstant { subpattern: ref pattern, .. } => {
141+
subpairs.push(MatchPair::new(place.clone(), pattern, cx));
142+
}
143+
144+
PatKind::Slice { ref prefix, ref slice, ref suffix }
145+
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
146+
cx.prefix_slice_suffix(&mut subpairs, &place, prefix, slice, suffix);
147+
}
148+
149+
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
150+
let downcast_place = place.clone().downcast(adt_def, variant_index); // `(x as Variant)`
151+
subpairs = cx.field_match_pairs(downcast_place, subpatterns);
152+
}
153+
154+
PatKind::Leaf { ref subpatterns } => {
155+
subpairs = cx.field_match_pairs(place.clone(), subpatterns);
156+
}
157+
158+
PatKind::Deref { ref subpattern } => {
159+
let place_builder = place.clone().deref();
160+
subpairs.push(MatchPair::new(place_builder, subpattern, cx));
161+
}
162+
}
163+
164+
MatchPair { place, pattern, subpairs }
120165
}
121166
}

0 commit comments

Comments
 (0)