Skip to content

Commit 4a5c24f

Browse files
committed
Move the recursive step out of prefix_slice_suffix
1 parent 80bb813 commit 4a5c24f

1 file changed

Lines changed: 59 additions & 68 deletions

File tree

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

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

15-
impl<'a, 'tcx> Builder<'a, 'tcx> {
16-
/// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an
17-
/// array pattern or slice pattern, and adds those trees to `match_pairs`.
18-
///
19-
/// Used internally by [`MatchPairTree::for_pattern`].
20-
fn prefix_slice_suffix(
21-
&mut self,
22-
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
23-
extra_data: &mut PatternExtraData<'tcx>,
24-
place: &PlaceBuilder<'tcx>,
25-
array_len: Option<u64>,
26-
prefix: &[Pat<'tcx>],
27-
opt_slice: &Option<Box<Pat<'tcx>>>,
28-
suffix: &[Pat<'tcx>],
29-
) {
30-
let prefix_len = u64::try_from(prefix.len()).unwrap();
31-
let suffix_len = u64::try_from(suffix.len()).unwrap();
32-
33-
// For slice patterns with a `..` followed by 0 or more suffix subpatterns,
34-
// the actual slice index of those subpatterns isn't statically known, so
35-
// we have to index them relative to the end of the slice.
36-
//
37-
// For array patterns, all subpatterns are indexed relative to the start.
38-
let (min_length, is_array) = match array_len {
39-
Some(len) => (len, true),
40-
None => (prefix_len + suffix_len, false),
41-
};
42-
43-
for (offset, subpattern) in (0u64..).zip(prefix) {
44-
let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
45-
let place = place.clone_project(elem);
46-
MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
47-
}
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));
44+
}
4845

49-
if let Some(subslice_pat) = opt_slice {
50-
let subslice = place.clone_project(PlaceElem::Subslice {
51-
from: prefix_len,
52-
to: if is_array { min_length - suffix_len } else { suffix_len },
53-
from_end: !is_array,
54-
});
55-
MatchPairTree::for_pattern(subslice, subslice_pat, self, match_pairs, extra_data);
56-
}
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,
51+
};
52+
let subplace = place.clone_project(elem);
53+
output_pairs.push((subplace, slice_subpat));
54+
}
5755

58-
for (end_offset, subpattern) in (1u64..).zip(suffix.iter().rev()) {
59-
let elem = ProjectionElem::ConstantIndex {
60-
offset: if is_array { min_length - end_offset } else { end_offset },
61-
min_length,
62-
from_end: !is_array,
63-
};
64-
let place = place.clone_project(elem);
65-
MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
66-
}
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));
6764
}
65+
66+
output_pairs
6867
}
6968

7069
impl<'tcx> MatchPairTree<'tcx> {
@@ -221,15 +220,11 @@ impl<'tcx> MatchPairTree<'tcx> {
221220
_ => None,
222221
};
223222
if let Some(array_len) = array_len {
224-
cx.prefix_slice_suffix(
225-
&mut subpairs,
226-
extra_data,
227-
&place_builder,
228-
Some(array_len),
229-
prefix,
230-
slice,
231-
suffix,
232-
);
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+
}
233228
} else {
234229
// If the array length couldn't be determined, ignore the
235230
// subpatterns and delayed-assert that compilation will fail.
@@ -245,15 +240,11 @@ impl<'tcx> MatchPairTree<'tcx> {
245240
None
246241
}
247242
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
248-
cx.prefix_slice_suffix(
249-
&mut subpairs,
250-
extra_data,
251-
&place_builder,
252-
None,
253-
prefix,
254-
slice,
255-
suffix,
256-
);
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+
}
257248

258249
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
259250
// This pattern is shaped like `[..]`. It can match a slice

0 commit comments

Comments
 (0)