Skip to content

Commit 9e54c30

Browse files
committed
Auto merge of #154943 - Zalathar:for-each-subpat, r=<try>
Move recursion out of `MatchPairTree::for_pattern` helpers
2 parents 1b8f2e4 + 4a5c24f commit 9e54c30

1 file changed

Lines changed: 65 additions & 86 deletions

File tree

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

Lines changed: 65 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -12,77 +12,58 @@ use crate::builder::matches::{
1212
FlatPat, MatchPairTree, PatConstKind, PatternExtraData, SliceLenOp, TestableCase,
1313
};
1414

15-
impl<'a, 'tcx> Builder<'a, 'tcx> {
16-
/// Builds and pushes [`MatchPairTree`] subtrees, one for each pattern in
17-
/// `subpatterns`, representing the fields of a [`PatKind::Variant`] or
18-
/// [`PatKind::Leaf`].
19-
///
20-
/// Used internally by [`MatchPairTree::for_pattern`].
21-
fn field_match_pairs(
22-
&mut self,
23-
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
24-
extra_data: &mut PatternExtraData<'tcx>,
25-
place: PlaceBuilder<'tcx>,
26-
subpatterns: &[FieldPat<'tcx>],
27-
) {
28-
for fieldpat in subpatterns {
29-
let place = place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
30-
MatchPairTree::for_pattern(place, &fieldpat.pattern, self, match_pairs, extra_data);
31-
}
15+
/// For an array or slice pattern's subpatterns (prefix/slice/suffix), returns a list
16+
/// of those subpatterns, each paired with a suitably-projected [`PlaceBuilder`].
17+
fn prefix_slice_suffix<'a, 'tcx>(
18+
place: &PlaceBuilder<'tcx>,
19+
array_len: Option<u64>, // Some for array patterns; None for slice patterns
20+
prefix: &'a [Pat<'tcx>],
21+
opt_slice: &'a Option<Box<Pat<'tcx>>>,
22+
suffix: &'a [Pat<'tcx>],
23+
) -> Vec<(PlaceBuilder<'tcx>, &'a Pat<'tcx>)> {
24+
let prefix_len = u64::try_from(prefix.len()).unwrap();
25+
let suffix_len = u64::try_from(suffix.len()).unwrap();
26+
27+
let mut output_pairs =
28+
Vec::with_capacity(prefix.len() + usize::from(opt_slice.is_some()) + suffix.len());
29+
30+
// For slice patterns with a `..` followed by 0 or more suffix subpatterns,
31+
// the actual slice index of those subpatterns isn't statically known, so
32+
// we have to index them relative to the end of the slice.
33+
//
34+
// For array patterns, all subpatterns are indexed relative to the start.
35+
let (min_length, is_array) = match array_len {
36+
Some(len) => (len, true),
37+
None => (prefix_len + suffix_len, false),
38+
};
39+
40+
for (offset, prefix_subpat) in (0u64..).zip(prefix) {
41+
let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
42+
let subplace = place.clone_project(elem);
43+
output_pairs.push((subplace, prefix_subpat));
3244
}
3345

34-
/// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an
35-
/// array pattern or slice pattern, and adds those trees to `match_pairs`.
36-
///
37-
/// Used internally by [`MatchPairTree::for_pattern`].
38-
fn prefix_slice_suffix(
39-
&mut self,
40-
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
41-
extra_data: &mut PatternExtraData<'tcx>,
42-
place: &PlaceBuilder<'tcx>,
43-
array_len: Option<u64>,
44-
prefix: &[Pat<'tcx>],
45-
opt_slice: &Option<Box<Pat<'tcx>>>,
46-
suffix: &[Pat<'tcx>],
47-
) {
48-
let prefix_len = u64::try_from(prefix.len()).unwrap();
49-
let suffix_len = u64::try_from(suffix.len()).unwrap();
50-
51-
// For slice patterns with a `..` followed by 0 or more suffix subpatterns,
52-
// the actual slice index of those subpatterns isn't statically known, so
53-
// we have to index them relative to the end of the slice.
54-
//
55-
// For array patterns, all subpatterns are indexed relative to the start.
56-
let (min_length, is_array) = match array_len {
57-
Some(len) => (len, true),
58-
None => (prefix_len + suffix_len, false),
46+
if let Some(slice_subpat) = opt_slice {
47+
let elem = PlaceElem::Subslice {
48+
from: prefix_len,
49+
to: if is_array { min_length - suffix_len } else { suffix_len },
50+
from_end: !is_array,
5951
};
52+
let subplace = place.clone_project(elem);
53+
output_pairs.push((subplace, slice_subpat));
54+
}
6055

61-
for (offset, subpattern) in (0u64..).zip(prefix) {
62-
let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
63-
let place = place.clone_project(elem);
64-
MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
65-
}
66-
67-
if let Some(subslice_pat) = opt_slice {
68-
let subslice = place.clone_project(PlaceElem::Subslice {
69-
from: prefix_len,
70-
to: if is_array { min_length - suffix_len } else { suffix_len },
71-
from_end: !is_array,
72-
});
73-
MatchPairTree::for_pattern(subslice, subslice_pat, self, match_pairs, extra_data);
74-
}
75-
76-
for (end_offset, subpattern) in (1u64..).zip(suffix.iter().rev()) {
77-
let elem = ProjectionElem::ConstantIndex {
78-
offset: if is_array { min_length - end_offset } else { end_offset },
79-
min_length,
80-
from_end: !is_array,
81-
};
82-
let place = place.clone_project(elem);
83-
MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
84-
}
56+
for (offset_from_end, suffix_subpat) in (1u64..).zip(suffix.iter().rev()) {
57+
let elem = ProjectionElem::ConstantIndex {
58+
offset: if is_array { min_length - offset_from_end } else { offset_from_end },
59+
min_length,
60+
from_end: !is_array,
61+
};
62+
let subplace = place.clone_project(elem);
63+
output_pairs.push((subplace, suffix_subpat));
8564
}
65+
66+
output_pairs
8667
}
8768

8869
impl<'tcx> MatchPairTree<'tcx> {
@@ -239,15 +220,11 @@ impl<'tcx> MatchPairTree<'tcx> {
239220
_ => None,
240221
};
241222
if let Some(array_len) = array_len {
242-
cx.prefix_slice_suffix(
243-
&mut subpairs,
244-
extra_data,
245-
&place_builder,
246-
Some(array_len),
247-
prefix,
248-
slice,
249-
suffix,
250-
);
223+
for (subplace, subpat) in
224+
prefix_slice_suffix(&place_builder, Some(array_len), prefix, slice, suffix)
225+
{
226+
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
227+
}
251228
} else {
252229
// If the array length couldn't be determined, ignore the
253230
// subpatterns and delayed-assert that compilation will fail.
@@ -263,15 +240,11 @@ impl<'tcx> MatchPairTree<'tcx> {
263240
None
264241
}
265242
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
266-
cx.prefix_slice_suffix(
267-
&mut subpairs,
268-
extra_data,
269-
&place_builder,
270-
None,
271-
prefix,
272-
slice,
273-
suffix,
274-
);
243+
for (subplace, subpat) in
244+
prefix_slice_suffix(&place_builder, None, prefix, slice, suffix)
245+
{
246+
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
247+
}
275248

276249
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
277250
// This pattern is shaped like `[..]`. It can match a slice
@@ -294,7 +267,10 @@ impl<'tcx> MatchPairTree<'tcx> {
294267

295268
PatKind::Variant { adt_def, variant_index, args: _, ref subpatterns } => {
296269
let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)`
297-
cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns);
270+
for &FieldPat { field, pattern: ref subpat } in subpatterns {
271+
let subplace = downcast_place.clone_project(PlaceElem::Field(field, subpat.ty));
272+
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
273+
}
298274

299275
// We treat non-exhaustive enums the same independent of the crate they are
300276
// defined in, to avoid differences in the operational semantics between crates.
@@ -308,7 +284,10 @@ impl<'tcx> MatchPairTree<'tcx> {
308284
}
309285

310286
PatKind::Leaf { ref subpatterns } => {
311-
cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns);
287+
for &FieldPat { field, pattern: ref subpat } in subpatterns {
288+
let subplace = place_builder.clone_project(PlaceElem::Field(field, subpat.ty));
289+
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
290+
}
312291
None
313292
}
314293

0 commit comments

Comments
 (0)