Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 219fa9f

Browse files
authoredFeb 6, 2025··
Unrolled build for rust-lang#136435
Rollup merge of rust-lang#136435 - Zalathar:thir-pat-stuff, r=Nadrieril Simplify some code for lowering THIR patterns I've been playing around with some radically different ways of storing THIR patterns, and while those experiments haven't yet produced a clear win, I have noticed various smaller things in the existing code that can be made a bit nicer. Some of the more significant changes: - With a little bit of extra effort (and thoughtful use of Arc), we can completely remove an entire layer of `'pat` lifetimes from the intermediate data structures used for match lowering. - In several places, lists of THIR patterns were being double-boxed for no apparent reason.
2 parents 79f82ad + 2f16696 commit 219fa9f

File tree

11 files changed

+148
-148
lines changed

11 files changed

+148
-148
lines changed
 

‎compiler/rustc_middle/src/thir.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use std::cmp::Ordering;
1212
use std::fmt;
1313
use std::ops::Index;
14+
use std::sync::Arc;
1415

1516
use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
1617
use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
@@ -618,7 +619,7 @@ pub enum InlineAsmOperand<'tcx> {
618619
#[derive(Debug, HashStable, TypeVisitable)]
619620
pub struct FieldPat<'tcx> {
620621
pub field: FieldIdx,
621-
pub pattern: Box<Pat<'tcx>>,
622+
pub pattern: Pat<'tcx>,
622623
}
623624

624625
#[derive(Debug, HashStable, TypeVisitable)]
@@ -679,7 +680,7 @@ impl<'tcx> Pat<'tcx> {
679680
Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
680681
Array { box ref prefix, ref slice, box ref suffix }
681682
| Slice { box ref prefix, ref slice, box ref suffix } => {
682-
prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
683+
prefix.iter().chain(slice.as_deref()).chain(suffix.iter()).for_each(|p| p.walk_(it))
683684
}
684685
}
685686
}
@@ -836,28 +837,28 @@ pub enum PatKind<'tcx> {
836837
subpattern: Box<Pat<'tcx>>,
837838
},
838839

839-
Range(Box<PatRange<'tcx>>),
840+
Range(Arc<PatRange<'tcx>>),
840841

841842
/// Matches against a slice, checking the length and extracting elements.
842843
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
843844
/// e.g., `&[ref xs @ ..]`.
844845
Slice {
845-
prefix: Box<[Box<Pat<'tcx>>]>,
846+
prefix: Box<[Pat<'tcx>]>,
846847
slice: Option<Box<Pat<'tcx>>>,
847-
suffix: Box<[Box<Pat<'tcx>>]>,
848+
suffix: Box<[Pat<'tcx>]>,
848849
},
849850

850851
/// Fixed match against an array; irrefutable.
851852
Array {
852-
prefix: Box<[Box<Pat<'tcx>>]>,
853+
prefix: Box<[Pat<'tcx>]>,
853854
slice: Option<Box<Pat<'tcx>>>,
854-
suffix: Box<[Box<Pat<'tcx>>]>,
855+
suffix: Box<[Pat<'tcx>]>,
855856
},
856857

857858
/// An or-pattern, e.g. `p | q`.
858859
/// Invariant: `pats.len() >= 2`.
859860
Or {
860-
pats: Box<[Box<Pat<'tcx>>]>,
861+
pats: Box<[Pat<'tcx>]>,
861862
},
862863

863864
/// A never pattern `!`.

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

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use rustc_middle::mir::*;
24
use rustc_middle::thir::{self, *};
35
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@@ -12,11 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1214
/// [`PatKind::Leaf`].
1315
///
1416
/// Used internally by [`MatchPairTree::for_pattern`].
15-
fn field_match_pairs<'pat>(
17+
fn field_match_pairs(
1618
&mut self,
1719
place: PlaceBuilder<'tcx>,
18-
subpatterns: &'pat [FieldPat<'tcx>],
19-
) -> Vec<MatchPairTree<'pat, 'tcx>> {
20+
subpatterns: &[FieldPat<'tcx>],
21+
) -> Vec<MatchPairTree<'tcx>> {
2022
subpatterns
2123
.iter()
2224
.map(|fieldpat| {
@@ -31,13 +33,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3133
/// array pattern or slice pattern, and adds those trees to `match_pairs`.
3234
///
3335
/// Used internally by [`MatchPairTree::for_pattern`].
34-
fn prefix_slice_suffix<'pat>(
36+
fn prefix_slice_suffix(
3537
&mut self,
36-
match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
38+
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
3739
place: &PlaceBuilder<'tcx>,
38-
prefix: &'pat [Box<Pat<'tcx>>],
39-
opt_slice: &'pat Option<Box<Pat<'tcx>>>,
40-
suffix: &'pat [Box<Pat<'tcx>>],
40+
prefix: &[Pat<'tcx>],
41+
opt_slice: &Option<Box<Pat<'tcx>>>,
42+
suffix: &[Pat<'tcx>],
4143
) {
4244
let tcx = self.tcx;
4345
let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
@@ -83,14 +85,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8385
}
8486
}
8587

86-
impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
88+
impl<'tcx> MatchPairTree<'tcx> {
8789
/// Recursively builds a match pair tree for the given pattern and its
8890
/// subpatterns.
8991
pub(in crate::builder) fn for_pattern(
9092
mut place_builder: PlaceBuilder<'tcx>,
91-
pattern: &'pat Pat<'tcx>,
93+
pattern: &Pat<'tcx>,
9294
cx: &mut Builder<'_, 'tcx>,
93-
) -> MatchPairTree<'pat, 'tcx> {
95+
) -> MatchPairTree<'tcx> {
9496
// Force the place type to the pattern's type.
9597
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
9698
if let Some(resolved) = place_builder.resolve_upvar(cx) {
@@ -125,7 +127,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
125127
if range.is_full_range(cx.tcx) == Some(true) {
126128
default_irrefutable()
127129
} else {
128-
TestCase::Range(range)
130+
TestCase::Range(Arc::clone(range))
129131
}
130132
}
131133

@@ -255,6 +257,12 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
255257
PatKind::Never => TestCase::Never,
256258
};
257259

258-
MatchPairTree { place, test_case, subpairs, pattern }
260+
MatchPairTree {
261+
place,
262+
test_case,
263+
subpairs,
264+
pattern_ty: pattern.ty,
265+
pattern_span: pattern.span,
266+
}
259267
}
260268
}

‎compiler/rustc_mir_build/src/builder/matches/mod.rs

Lines changed: 71 additions & 81 deletions
Large diffs are not rendered by default.

‎compiler/rustc_mir_build/src/builder/matches/simplify.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2323
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
2424
/// ascriptions in `extra_data`.
2525
#[instrument(skip(self), level = "debug")]
26-
pub(super) fn simplify_match_pairs<'pat>(
26+
pub(super) fn simplify_match_pairs(
2727
&mut self,
28-
match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
28+
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
2929
extra_data: &mut PatternExtraData<'tcx>,
3030
) {
3131
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the

‎compiler/rustc_mir_build/src/builder/matches/test.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// the candidates based on the result.
77

88
use std::cmp::Ordering;
9+
use std::sync::Arc;
910

1011
use rustc_data_structures::fx::FxIndexMap;
1112
use rustc_hir::{LangItem, RangeEnd};
@@ -26,20 +27,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2627
/// Identifies what test is needed to decide if `match_pair` is applicable.
2728
///
2829
/// It is a bug to call this with a not-fully-simplified pattern.
29-
pub(super) fn pick_test_for_match_pair<'pat>(
30+
pub(super) fn pick_test_for_match_pair(
3031
&mut self,
31-
match_pair: &MatchPairTree<'pat, 'tcx>,
32+
match_pair: &MatchPairTree<'tcx>,
3233
) -> Test<'tcx> {
3334
let kind = match match_pair.test_case {
3435
TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
3536

36-
TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If,
37-
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt,
38-
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty },
37+
TestCase::Constant { .. } if match_pair.pattern_ty.is_bool() => TestKind::If,
38+
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern_ty) => TestKind::SwitchInt,
39+
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern_ty },
3940

40-
TestCase::Range(range) => {
41-
assert_eq!(range.ty, match_pair.pattern.ty);
42-
TestKind::Range(Box::new(range.clone()))
41+
TestCase::Range(ref range) => {
42+
assert_eq!(range.ty, match_pair.pattern_ty);
43+
TestKind::Range(Arc::clone(range))
4344
}
4445

4546
TestCase::Slice { len, variable_length } => {
@@ -56,13 +57,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5657
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
5758

5859
TestCase::Irrefutable { .. } => span_bug!(
59-
match_pair.pattern.span,
60+
match_pair.pattern_span,
6061
"simplifiable pattern found: {:?}",
61-
match_pair.pattern
62+
match_pair.pattern_span
6263
),
6364
};
6465

65-
Test { span: match_pair.pattern.span, kind }
66+
Test { span: match_pair.pattern_span, kind }
6667
}
6768

6869
#[instrument(skip(self, target_blocks, place), level = "debug")]
@@ -521,8 +522,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
521522
&mut self,
522523
test_place: Place<'tcx>,
523524
test: &Test<'tcx>,
524-
candidate: &mut Candidate<'_, 'tcx>,
525-
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'_, 'tcx>>>,
525+
candidate: &mut Candidate<'tcx>,
526+
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'tcx>>>,
526527
) -> Option<TestBranch<'tcx>> {
527528
// Find the match_pair for this place (if any). At present,
528529
// afaik, there can be at most one. (In the future, if we
@@ -558,22 +559,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
558559
// FIXME(#29623) we could use PatKind::Range to rule
559560
// things out here, in some cases.
560561
(TestKind::SwitchInt, &TestCase::Constant { value })
561-
if is_switch_ty(match_pair.pattern.ty) =>
562+
if is_switch_ty(match_pair.pattern_ty) =>
562563
{
563564
// An important invariant of candidate sorting is that a candidate
564565
// must not match in multiple branches. For `SwitchInt` tests, adding
565566
// a new value might invalidate that property for range patterns that
566567
// have already been sorted into the failure arm, so we must take care
567568
// not to add such values here.
568-
let is_covering_range = |test_case: &TestCase<'_, 'tcx>| {
569+
let is_covering_range = |test_case: &TestCase<'tcx>| {
569570
test_case.as_range().is_some_and(|range| {
570571
matches!(
571572
range.contains(value, self.tcx, self.typing_env()),
572573
None | Some(true)
573574
)
574575
})
575576
};
576-
let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| {
577+
let is_conflicting_candidate = |candidate: &&mut Candidate<'tcx>| {
577578
candidate
578579
.match_pairs
579580
.iter()
@@ -685,8 +686,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
685686
}
686687
}
687688

688-
(TestKind::Range(test), &TestCase::Range(pat)) => {
689-
if test.as_ref() == pat {
689+
(TestKind::Range(test), TestCase::Range(pat)) => {
690+
if test == pat {
690691
fully_matched = true;
691692
Some(TestBranch::Success)
692693
} else {

‎compiler/rustc_mir_build/src/builder/matches/util.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6767
/// a MIR pass run after borrow checking.
6868
pub(super) fn collect_fake_borrows<'tcx>(
6969
cx: &mut Builder<'_, 'tcx>,
70-
candidates: &[Candidate<'_, 'tcx>],
70+
candidates: &[Candidate<'tcx>],
7171
temp_span: Span,
7272
scrutinee_base: PlaceBase,
7373
) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
@@ -135,7 +135,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
135135
}
136136
}
137137

138-
fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
138+
fn visit_candidate(&mut self, candidate: &Candidate<'tcx>) {
139139
for binding in &candidate.extra_data.bindings {
140140
self.visit_binding(binding);
141141
}
@@ -144,7 +144,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
144144
}
145145
}
146146

147-
fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
147+
fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'tcx>) {
148148
for binding in &flat_pat.extra_data.bindings {
149149
self.visit_binding(binding);
150150
}
@@ -153,7 +153,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
153153
}
154154
}
155155

156-
fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
156+
fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'tcx>) {
157157
if let TestCase::Or { pats, .. } = &match_pair.test_case {
158158
for flat_pat in pats.iter() {
159159
self.visit_flat_pat(flat_pat)

‎compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -676,12 +676,14 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
676676
let mut interpreted_as_const = None;
677677
let mut interpreted_as_const_sugg = None;
678678

679-
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. }
680-
| PatKind::AscribeUserType {
681-
subpattern:
682-
box Pat { kind: PatKind::ExpandedConstant { def_id, is_inline: false, .. }, .. },
683-
..
684-
} = pat.kind
679+
// These next few matches want to peek through `AscribeUserType` to see
680+
// the underlying pattern.
681+
let mut unpeeled_pat = pat;
682+
while let PatKind::AscribeUserType { ref subpattern, .. } = unpeeled_pat.kind {
683+
unpeeled_pat = subpattern;
684+
}
685+
686+
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = unpeeled_pat.kind
685687
&& let DefKind::Const = self.tcx.def_kind(def_id)
686688
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
687689
// We filter out paths with multiple path::segments.
@@ -692,11 +694,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
692694
// When we encounter a constant as the binding name, point at the `const` definition.
693695
interpreted_as_const = Some(span);
694696
interpreted_as_const_sugg = Some(InterpretedAsConst { span: pat.span, variable });
695-
} else if let PatKind::Constant { .. }
696-
| PatKind::AscribeUserType {
697-
subpattern: box Pat { kind: PatKind::Constant { .. }, .. },
698-
..
699-
} = pat.kind
697+
} else if let PatKind::Constant { .. } = unpeeled_pat.kind
700698
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
701699
{
702700
// If the pattern to match is an integer literal:

‎compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl<'tcx> ConstToPat<'tcx> {
208208
let field = FieldIdx::new(idx);
209209
// Patterns can only use monomorphic types.
210210
let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
211-
FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
211+
FieldPat { field, pattern: *self.valtree_to_pat(val, ty) }
212212
})
213213
.collect()
214214
}
@@ -277,7 +277,7 @@ impl<'tcx> ConstToPat<'tcx> {
277277
prefix: cv
278278
.unwrap_branch()
279279
.iter()
280-
.map(|val| self.valtree_to_pat(*val, *elem_ty))
280+
.map(|val| *self.valtree_to_pat(*val, *elem_ty))
281281
.collect(),
282282
slice: None,
283283
suffix: Box::new([]),
@@ -286,7 +286,7 @@ impl<'tcx> ConstToPat<'tcx> {
286286
prefix: cv
287287
.unwrap_branch()
288288
.iter()
289-
.map(|val| self.valtree_to_pat(*val, *elem_ty))
289+
.map(|val| *self.valtree_to_pat(*val, *elem_ty))
290290
.collect(),
291291
slice: None,
292292
suffix: Box::new([]),

‎compiler/rustc_mir_build/src/thir/pattern/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod check_match;
44
mod const_to_pat;
55

66
use std::cmp::Ordering;
7+
use std::sync::Arc;
78

89
use rustc_abi::{FieldIdx, Integer};
910
use rustc_errors::MultiSpan;
@@ -262,7 +263,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
262263
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
263264

264265
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
265-
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
266+
let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
266267
match (end, cmp) {
267268
// `x..y` where `x < y`.
268269
(RangeEnd::Excluded, Some(Ordering::Less)) => {}
@@ -418,7 +419,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
418419
.iter()
419420
.map(|field| FieldPat {
420421
field: self.typeck_results.field_index(field.hir_id),
421-
pattern: self.lower_pattern(field.pat),
422+
pattern: *self.lower_pattern(field.pat),
422423
})
423424
.collect();
424425

@@ -446,13 +447,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
446447
.enumerate_and_adjust(expected_len, gap_pos)
447448
.map(|(i, subpattern)| FieldPat {
448449
field: FieldIdx::new(i),
449-
pattern: self.lower_pattern(subpattern),
450+
pattern: *self.lower_pattern(subpattern),
450451
})
451452
.collect()
452453
}
453454

454-
fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box<Pat<'tcx>>]> {
455-
pats.iter().map(|p| self.lower_pattern(p)).collect()
455+
fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
456+
pats.iter().map(|p| *self.lower_pattern(p)).collect()
456457
}
457458

458459
fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {

‎compiler/rustc_mir_build/src/thir/print.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
643643
print_indented!(self, "}", depth_lvl);
644644
}
645645

646-
fn print_pat(&mut self, pat: &Box<Pat<'tcx>>, depth_lvl: usize) {
647-
let Pat { ty, span, kind } = &**pat;
646+
fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) {
647+
let &Pat { ty, span, ref kind } = pat;
648648

649649
print_indented!(self, "Pat: {", depth_lvl);
650650
print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);

‎compiler/rustc_ty_utils/src/consts.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
373373

374374
match pat.kind {
375375
thir::PatKind::Constant { value } => value.has_non_region_param(),
376-
thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
376+
thir::PatKind::Range(ref range) => {
377+
let &thir::PatRange { lo, hi, .. } = range.as_ref();
377378
lo.has_non_region_param() || hi.has_non_region_param()
378379
}
379380
_ => false,

0 commit comments

Comments
 (0)
This repository has been archived.