Skip to content

Commit ac7601f

Browse files
committed
Auto merge of rust-lang#136421 - Zalathar:arc-pat, r=<try>
[DO NOT MERGE] Store THIR patterns in Arc instead of Box (Checking if this has any measurable effect on perf.) r? ghost `@rustbot` experimental
2 parents 8239a37 + 0201b00 commit ac7601f

File tree

14 files changed

+205
-188
lines changed

14 files changed

+205
-188
lines changed

compiler/rustc_middle/src/thir.rs

+47-38
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};
@@ -108,7 +109,7 @@ pub enum BodyTy<'tcx> {
108109
#[derive(Clone, Debug, HashStable)]
109110
pub struct Param<'tcx> {
110111
/// The pattern that appears in the parameter list, or None for implicit parameters.
111-
pub pat: Option<Box<Pat<'tcx>>>,
112+
pub pat: Option<Arc<Pat<'tcx>>>,
112113
/// The possibly inferred type.
113114
pub ty: Ty<'tcx>,
114115
/// Span of the explicitly provided type, or None if inferred for closures.
@@ -231,7 +232,7 @@ pub enum StmtKind<'tcx> {
231232
/// `let <PAT> = ...`
232233
///
233234
/// If a type annotation is included, it is added as an ascription pattern.
234-
pattern: Box<Pat<'tcx>>,
235+
pattern: Arc<Pat<'tcx>>,
235236

236237
/// `let pat: ty = <INIT>`
237238
initializer: Option<ExprId>,
@@ -379,7 +380,7 @@ pub enum ExprKind<'tcx> {
379380
/// (Not to be confused with [`StmtKind::Let`], which is a normal `let` statement.)
380381
Let {
381382
expr: ExprId,
382-
pat: Box<Pat<'tcx>>,
383+
pat: Arc<Pat<'tcx>>,
383384
},
384385
/// A `match` expression.
385386
Match {
@@ -571,7 +572,7 @@ pub struct FruInfo<'tcx> {
571572
/// A `match` arm.
572573
#[derive(Clone, Debug, HashStable)]
573574
pub struct Arm<'tcx> {
574-
pub pattern: Box<Pat<'tcx>>,
575+
pub pattern: Arc<Pat<'tcx>>,
575576
pub guard: Option<ExprId>,
576577
pub body: ExprId,
577578
pub lint_level: LintLevel,
@@ -628,7 +629,7 @@ pub enum InlineAsmOperand<'tcx> {
628629
#[derive(Clone, Debug, HashStable, TypeVisitable)]
629630
pub struct FieldPat<'tcx> {
630631
pub field: FieldIdx,
631-
pub pattern: Box<Pat<'tcx>>,
632+
pub pattern: Arc<Pat<'tcx>>,
632633
}
633634

634635
#[derive(Clone, Debug, HashStable, TypeVisitable)]
@@ -647,11 +648,17 @@ impl<'tcx> Pat<'tcx> {
647648
_ => None,
648649
}
649650
}
651+
}
650652

653+
impl<'tcx> Thir<'tcx> {
651654
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
652655
/// `match foo() { Some(a) => (), None => () }`
653-
pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) {
654-
self.walk_always(|p| {
656+
pub fn each_pat_binding(
657+
&self,
658+
pat: &Pat<'tcx>,
659+
mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span),
660+
) {
661+
self.walk_pat_always(pat, |p| {
655662
if let PatKind::Binding { name, mode, ty, .. } = p.kind {
656663
f(name, mode.0, ty, p.span);
657664
}
@@ -661,17 +668,17 @@ impl<'tcx> Pat<'tcx> {
661668
/// Walk the pattern in left-to-right order.
662669
///
663670
/// If `it(pat)` returns `false`, the children are not visited.
664-
pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
665-
self.walk_(&mut it)
671+
pub fn walk_pat(&self, pat: &Pat<'tcx>, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
672+
self.walk_pat_inner(pat, &mut it);
666673
}
667674

668-
fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
669-
if !it(self) {
675+
fn walk_pat_inner(&self, pat: &Pat<'tcx>, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
676+
if !it(pat) {
670677
return;
671678
}
672679

673680
use PatKind::*;
674-
match &self.kind {
681+
match &pat.kind {
675682
Wild
676683
| Never
677684
| Range(..)
@@ -682,22 +689,24 @@ impl<'tcx> Pat<'tcx> {
682689
| Binding { subpattern: Some(subpattern), .. }
683690
| Deref { subpattern }
684691
| DerefPattern { subpattern, .. }
685-
| ExpandedConstant { subpattern, .. } => subpattern.walk_(it),
692+
| ExpandedConstant { subpattern, .. } => self.walk_pat_inner(subpattern, it),
686693
Leaf { subpatterns } | Variant { subpatterns, .. } => {
687-
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
694+
subpatterns.iter().for_each(|field| self.walk_pat_inner(&field.pattern, it))
688695
}
689-
Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
696+
Or { pats } => pats.iter().for_each(|p| self.walk_pat_inner(p, it)),
690697
Array { box ref prefix, ref slice, box ref suffix }
691-
| Slice { box ref prefix, ref slice, box ref suffix } => {
692-
prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
693-
}
698+
| Slice { box ref prefix, ref slice, box ref suffix } => prefix
699+
.iter()
700+
.chain(slice.iter())
701+
.chain(suffix.iter())
702+
.for_each(|p| self.walk_pat_inner(p, it)),
694703
}
695704
}
696705

697706
/// Whether the pattern has a `PatKind::Error` nested within.
698-
pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> {
707+
pub fn pat_error_reported(&self, pat: &Pat<'tcx>) -> Result<(), ErrorGuaranteed> {
699708
let mut error = None;
700-
self.walk(|pat| {
709+
self.walk_pat(pat, |pat| {
701710
if let PatKind::Error(e) = pat.kind
702711
&& error.is_none()
703712
{
@@ -714,23 +723,23 @@ impl<'tcx> Pat<'tcx> {
714723
/// Walk the pattern in left-to-right order.
715724
///
716725
/// If you always want to recurse, prefer this method over `walk`.
717-
pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
718-
self.walk(|p| {
726+
pub fn walk_pat_always(&self, pat: &Pat<'tcx>, mut it: impl FnMut(&Pat<'tcx>)) {
727+
self.walk_pat(pat, |p| {
719728
it(p);
720729
true
721730
})
722731
}
723732

724733
/// Whether this a never pattern.
725-
pub fn is_never_pattern(&self) -> bool {
734+
pub fn is_never_pattern(&self, pat: &Pat<'tcx>) -> bool {
726735
let mut is_never_pattern = false;
727-
self.walk(|pat| match &pat.kind {
736+
self.walk_pat(pat, |pat| match &pat.kind {
728737
PatKind::Never => {
729738
is_never_pattern = true;
730739
false
731740
}
732741
PatKind::Or { pats } => {
733-
is_never_pattern = pats.iter().all(|p| p.is_never_pattern());
742+
is_never_pattern = pats.iter().all(|p| self.is_never_pattern(p));
734743
false
735744
}
736745
_ => true,
@@ -770,7 +779,7 @@ pub enum PatKind<'tcx> {
770779

771780
AscribeUserType {
772781
ascription: Ascription<'tcx>,
773-
subpattern: Box<Pat<'tcx>>,
782+
subpattern: Arc<Pat<'tcx>>,
774783
},
775784

776785
/// `x`, `ref x`, `x @ P`, etc.
@@ -781,7 +790,7 @@ pub enum PatKind<'tcx> {
781790
#[type_visitable(ignore)]
782791
var: LocalVarId,
783792
ty: Ty<'tcx>,
784-
subpattern: Option<Box<Pat<'tcx>>>,
793+
subpattern: Option<Arc<Pat<'tcx>>>,
785794
/// Is this the leftmost occurrence of the binding, i.e., is `var` the
786795
/// `HirId` of this pattern?
787796
is_primary: bool,
@@ -804,12 +813,12 @@ pub enum PatKind<'tcx> {
804813

805814
/// `box P`, `&P`, `&mut P`, etc.
806815
Deref {
807-
subpattern: Box<Pat<'tcx>>,
816+
subpattern: Arc<Pat<'tcx>>,
808817
},
809818

810819
/// Deref pattern, written `box P` for now.
811820
DerefPattern {
812-
subpattern: Box<Pat<'tcx>>,
821+
subpattern: Arc<Pat<'tcx>>,
813822
mutability: hir::Mutability,
814823
},
815824

@@ -843,31 +852,31 @@ pub enum PatKind<'tcx> {
843852
/// Otherwise, the actual pattern that the constant lowered to. As with
844853
/// other constants, inline constants are matched structurally where
845854
/// possible.
846-
subpattern: Box<Pat<'tcx>>,
855+
subpattern: Arc<Pat<'tcx>>,
847856
},
848857

849-
Range(Box<PatRange<'tcx>>),
858+
Range(Arc<PatRange<'tcx>>),
850859

851860
/// Matches against a slice, checking the length and extracting elements.
852861
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
853862
/// e.g., `&[ref xs @ ..]`.
854863
Slice {
855-
prefix: Box<[Box<Pat<'tcx>>]>,
856-
slice: Option<Box<Pat<'tcx>>>,
857-
suffix: Box<[Box<Pat<'tcx>>]>,
864+
prefix: Box<[Arc<Pat<'tcx>>]>,
865+
slice: Option<Arc<Pat<'tcx>>>,
866+
suffix: Box<[Arc<Pat<'tcx>>]>,
858867
},
859868

860869
/// Fixed match against an array; irrefutable.
861870
Array {
862-
prefix: Box<[Box<Pat<'tcx>>]>,
863-
slice: Option<Box<Pat<'tcx>>>,
864-
suffix: Box<[Box<Pat<'tcx>>]>,
871+
prefix: Box<[Arc<Pat<'tcx>>]>,
872+
slice: Option<Arc<Pat<'tcx>>>,
873+
suffix: Box<[Arc<Pat<'tcx>>]>,
865874
},
866875

867876
/// An or-pattern, e.g. `p | q`.
868877
/// Invariant: `pats.len() >= 2`.
869878
Or {
870-
pats: Box<[Box<Pat<'tcx>>]>,
879+
pats: Box<[Arc<Pat<'tcx>>]>,
871880
},
872881

873882
/// A never pattern `!`.

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

+16-12
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: &[Arc<Pat<'tcx>>],
41+
opt_slice: &Option<Arc<Pat<'tcx>>>,
42+
suffix: &[Arc<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,16 @@ 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: &Arc<Pat<'tcx>>,
9294
cx: &mut Builder<'_, 'tcx>,
93-
) -> MatchPairTree<'pat, 'tcx> {
95+
) -> MatchPairTree<'tcx> {
96+
let pattern = Arc::clone(pattern);
97+
9498
// Force the place type to the pattern's type.
9599
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
96100
if let Some(resolved) = place_builder.resolve_upvar(cx) {
@@ -125,7 +129,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
125129
if range.is_full_range(cx.tcx) == Some(true) {
126130
default_irrefutable()
127131
} else {
128-
TestCase::Range(range)
132+
TestCase::Range(Arc::clone(range))
129133
}
130134
}
131135

0 commit comments

Comments
 (0)