From 80bb81359bc045046a05402bb559b4665eb78f37 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 11 Apr 2026 11:53:05 +1000 Subject: [PATCH 1/2] Inline `field_match_pairs` into its callers --- .../src/builder/matches/match_pair.rs | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index bd18a215aea70..6fb425aeba381 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -13,24 +13,6 @@ use crate::builder::matches::{ }; impl<'a, 'tcx> Builder<'a, 'tcx> { - /// Builds and pushes [`MatchPairTree`] subtrees, one for each pattern in - /// `subpatterns`, representing the fields of a [`PatKind::Variant`] or - /// [`PatKind::Leaf`]. - /// - /// Used internally by [`MatchPairTree::for_pattern`]. - fn field_match_pairs( - &mut self, - match_pairs: &mut Vec>, - extra_data: &mut PatternExtraData<'tcx>, - place: PlaceBuilder<'tcx>, - subpatterns: &[FieldPat<'tcx>], - ) { - for fieldpat in subpatterns { - let place = place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty)); - MatchPairTree::for_pattern(place, &fieldpat.pattern, self, match_pairs, extra_data); - } - } - /// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an /// array pattern or slice pattern, and adds those trees to `match_pairs`. /// @@ -294,7 +276,10 @@ impl<'tcx> MatchPairTree<'tcx> { PatKind::Variant { adt_def, variant_index, args: _, ref subpatterns } => { let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)` - cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns); + for &FieldPat { field, pattern: ref subpat } in subpatterns { + let subplace = downcast_place.clone_project(PlaceElem::Field(field, subpat.ty)); + MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data); + } // We treat non-exhaustive enums the same independent of the crate they are // defined in, to avoid differences in the operational semantics between crates. @@ -308,7 +293,10 @@ impl<'tcx> MatchPairTree<'tcx> { } PatKind::Leaf { ref subpatterns } => { - cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns); + for &FieldPat { field, pattern: ref subpat } in subpatterns { + let subplace = place_builder.clone_project(PlaceElem::Field(field, subpat.ty)); + MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data); + } None } From 4a5c24f3cb232bb30e21cc2b08861c90d837f56f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 11 Apr 2026 12:11:51 +1000 Subject: [PATCH 2/2] Move the recursive step out of `prefix_slice_suffix` --- .../src/builder/matches/match_pair.rs | 127 ++++++++---------- 1 file changed, 59 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 6fb425aeba381..e2d00238e2d59 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -12,59 +12,58 @@ use crate::builder::matches::{ FlatPat, MatchPairTree, PatConstKind, PatternExtraData, SliceLenOp, TestableCase, }; -impl<'a, 'tcx> Builder<'a, 'tcx> { - /// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an - /// array pattern or slice pattern, and adds those trees to `match_pairs`. - /// - /// Used internally by [`MatchPairTree::for_pattern`]. - fn prefix_slice_suffix( - &mut self, - match_pairs: &mut Vec>, - extra_data: &mut PatternExtraData<'tcx>, - place: &PlaceBuilder<'tcx>, - array_len: Option, - prefix: &[Pat<'tcx>], - opt_slice: &Option>>, - suffix: &[Pat<'tcx>], - ) { - let prefix_len = u64::try_from(prefix.len()).unwrap(); - let suffix_len = u64::try_from(suffix.len()).unwrap(); - - // For slice patterns with a `..` followed by 0 or more suffix subpatterns, - // the actual slice index of those subpatterns isn't statically known, so - // we have to index them relative to the end of the slice. - // - // For array patterns, all subpatterns are indexed relative to the start. - let (min_length, is_array) = match array_len { - Some(len) => (len, true), - None => (prefix_len + suffix_len, false), - }; - - for (offset, subpattern) in (0u64..).zip(prefix) { - let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false }; - let place = place.clone_project(elem); - MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data) - } +/// For an array or slice pattern's subpatterns (prefix/slice/suffix), returns a list +/// of those subpatterns, each paired with a suitably-projected [`PlaceBuilder`]. +fn prefix_slice_suffix<'a, 'tcx>( + place: &PlaceBuilder<'tcx>, + array_len: Option, // Some for array patterns; None for slice patterns + prefix: &'a [Pat<'tcx>], + opt_slice: &'a Option>>, + suffix: &'a [Pat<'tcx>], +) -> Vec<(PlaceBuilder<'tcx>, &'a Pat<'tcx>)> { + let prefix_len = u64::try_from(prefix.len()).unwrap(); + let suffix_len = u64::try_from(suffix.len()).unwrap(); + + let mut output_pairs = + Vec::with_capacity(prefix.len() + usize::from(opt_slice.is_some()) + suffix.len()); + + // For slice patterns with a `..` followed by 0 or more suffix subpatterns, + // the actual slice index of those subpatterns isn't statically known, so + // we have to index them relative to the end of the slice. + // + // For array patterns, all subpatterns are indexed relative to the start. + let (min_length, is_array) = match array_len { + Some(len) => (len, true), + None => (prefix_len + suffix_len, false), + }; + + for (offset, prefix_subpat) in (0u64..).zip(prefix) { + let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false }; + let subplace = place.clone_project(elem); + output_pairs.push((subplace, prefix_subpat)); + } - if let Some(subslice_pat) = opt_slice { - let subslice = place.clone_project(PlaceElem::Subslice { - from: prefix_len, - to: if is_array { min_length - suffix_len } else { suffix_len }, - from_end: !is_array, - }); - MatchPairTree::for_pattern(subslice, subslice_pat, self, match_pairs, extra_data); - } + if let Some(slice_subpat) = opt_slice { + let elem = PlaceElem::Subslice { + from: prefix_len, + to: if is_array { min_length - suffix_len } else { suffix_len }, + from_end: !is_array, + }; + let subplace = place.clone_project(elem); + output_pairs.push((subplace, slice_subpat)); + } - for (end_offset, subpattern) in (1u64..).zip(suffix.iter().rev()) { - let elem = ProjectionElem::ConstantIndex { - offset: if is_array { min_length - end_offset } else { end_offset }, - min_length, - from_end: !is_array, - }; - let place = place.clone_project(elem); - MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data) - } + for (offset_from_end, suffix_subpat) in (1u64..).zip(suffix.iter().rev()) { + let elem = ProjectionElem::ConstantIndex { + offset: if is_array { min_length - offset_from_end } else { offset_from_end }, + min_length, + from_end: !is_array, + }; + let subplace = place.clone_project(elem); + output_pairs.push((subplace, suffix_subpat)); } + + output_pairs } impl<'tcx> MatchPairTree<'tcx> { @@ -221,15 +220,11 @@ impl<'tcx> MatchPairTree<'tcx> { _ => None, }; if let Some(array_len) = array_len { - cx.prefix_slice_suffix( - &mut subpairs, - extra_data, - &place_builder, - Some(array_len), - prefix, - slice, - suffix, - ); + for (subplace, subpat) in + prefix_slice_suffix(&place_builder, Some(array_len), prefix, slice, suffix) + { + MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data); + } } else { // If the array length couldn't be determined, ignore the // subpatterns and delayed-assert that compilation will fail. @@ -245,15 +240,11 @@ impl<'tcx> MatchPairTree<'tcx> { None } PatKind::Slice { ref prefix, ref slice, ref suffix } => { - cx.prefix_slice_suffix( - &mut subpairs, - extra_data, - &place_builder, - None, - prefix, - slice, - suffix, - ); + for (subplace, subpat) in + prefix_slice_suffix(&place_builder, None, prefix, slice, suffix) + { + MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data); + } if prefix.is_empty() && slice.is_some() && suffix.is_empty() { // This pattern is shaped like `[..]`. It can match a slice