Skip to content

Commit 45fc6fe

Browse files
committed
Move recursion out of MatchPairTree::for_pattern helpers
The helper functions now just iterate over the relevant subpatterns, while leaving recursion up to the main function. This avoids passing parameters that were only used for recursive plumbing, and consolidates all recursive calls into `for_pattern` itself, which should make it easier to experiment with changes to the recursive structure. There should be no change to compiler behaviour.
1 parent 49b6ac0 commit 45fc6fe

1 file changed

Lines changed: 76 additions & 74 deletions

File tree

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

Lines changed: 76 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -12,76 +12,66 @@ 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+
/// Visits each of the immediate subpatterns of a tuple, struct, or enum-variant pattern,
16+
/// along with a suitably-projected [`PlaceBuilder`] for each.
17+
fn for_each_field_subpat<'tcx>(
18+
place: &PlaceBuilder<'tcx>,
19+
subpatterns: &[FieldPat<'tcx>],
20+
mut callback_fn: impl FnMut(PlaceBuilder<'tcx>, &Pat<'tcx>),
21+
) {
22+
for fieldpat in subpatterns {
23+
let subplace = place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
24+
callback_fn(subplace, &fieldpat.pattern);
3225
}
26+
}
3327

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),
59-
};
60-
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-
}
28+
/// Visits each of the immediate subpatterns of an array pattern or slice pattern,
29+
/// along with a suitably-projected [`PlaceBuilder`] for each.
30+
fn for_each_subpat_of_array_or_slice<'tcx>(
31+
place: &PlaceBuilder<'tcx>,
32+
array_len: Option<u64>, // Some for array patterns, None for slice patterns
33+
prefix: &[Pat<'tcx>],
34+
opt_middle: &Option<Box<Pat<'tcx>>>,
35+
suffix: &[Pat<'tcx>],
36+
mut callback_fn: impl FnMut(PlaceBuilder<'tcx>, &Pat<'tcx>),
37+
) {
38+
let prefix_len = u64::try_from(prefix.len()).unwrap();
39+
let suffix_len = u64::try_from(suffix.len()).unwrap();
40+
41+
// For slice patterns with a `..` followed by 0 or more suffix subpatterns,
42+
// the actual slice index of those subpatterns isn't statically known, so
43+
// we have to index them relative to the end of the slice.
44+
//
45+
// For array patterns, all subpatterns are indexed relative to the start.
46+
let (min_length, is_array) = match array_len {
47+
Some(len) => (len, true),
48+
None => (prefix_len + suffix_len, false),
49+
};
50+
51+
for (offset, prefix_subpat) in (0u64..).zip(prefix) {
52+
let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
53+
let subplace = place.clone_project(elem);
54+
callback_fn(subplace, prefix_subpat);
55+
}
6656

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-
}
57+
if let Some(middle_subpat) = opt_middle {
58+
let elem = PlaceElem::Subslice {
59+
from: prefix_len,
60+
to: if is_array { min_length - suffix_len } else { suffix_len },
61+
from_end: !is_array,
62+
};
63+
let subplace = place.clone_project(elem);
64+
callback_fn(subplace, middle_subpat);
65+
}
7566

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-
}
67+
for (end_offset, suffix_subpat) in (1u64..).zip(suffix.iter().rev()) {
68+
let elem = ProjectionElem::ConstantIndex {
69+
offset: if is_array { min_length - end_offset } else { end_offset },
70+
min_length,
71+
from_end: !is_array,
72+
};
73+
let subplace = place.clone_project(elem);
74+
callback_fn(subplace, suffix_subpat);
8575
}
8676
}
8777

@@ -238,14 +228,21 @@ impl<'tcx> MatchPairTree<'tcx> {
238228
_ => None,
239229
};
240230
if let Some(array_len) = array_len {
241-
cx.prefix_slice_suffix(
242-
&mut subpairs,
243-
extra_data,
231+
for_each_subpat_of_array_or_slice(
244232
&place_builder,
245233
Some(array_len),
246234
prefix,
247235
slice,
248236
suffix,
237+
|subplace, subpat| {
238+
MatchPairTree::for_pattern(
239+
subplace,
240+
subpat,
241+
cx,
242+
&mut subpairs,
243+
extra_data,
244+
);
245+
},
249246
);
250247
} else {
251248
// If the array length couldn't be determined, ignore the
@@ -262,14 +259,15 @@ impl<'tcx> MatchPairTree<'tcx> {
262259
None
263260
}
264261
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
265-
cx.prefix_slice_suffix(
266-
&mut subpairs,
267-
extra_data,
262+
for_each_subpat_of_array_or_slice(
268263
&place_builder,
269264
None,
270265
prefix,
271266
slice,
272267
suffix,
268+
|subplace, subpat| {
269+
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
270+
},
273271
);
274272

275273
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
@@ -293,7 +291,9 @@ impl<'tcx> MatchPairTree<'tcx> {
293291

294292
PatKind::Variant { adt_def, variant_index, args: _, ref subpatterns } => {
295293
let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)`
296-
cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns);
294+
for_each_field_subpat(&downcast_place, subpatterns, |subplace, subpat| {
295+
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
296+
});
297297

298298
// We treat non-exhaustive enums the same independent of the crate they are
299299
// defined in, to avoid differences in the operational semantics between crates.
@@ -307,7 +307,9 @@ impl<'tcx> MatchPairTree<'tcx> {
307307
}
308308

309309
PatKind::Leaf { ref subpatterns } => {
310-
cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns);
310+
for_each_field_subpat(&place_builder, subpatterns, |subplace, subpat| {
311+
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
312+
});
311313
None
312314
}
313315

0 commit comments

Comments
 (0)