From 248449870d282c8e509c321eb2cd01fcdcda6efb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 28 Jan 2025 18:47:47 +1100 Subject: [PATCH 1/6] Don't demand `&Box` in `print_pat` --- compiler/rustc_mir_build/src/thir/print.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 729c8f784ba9f..9ab87dd99ffc0 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -643,8 +643,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "}", depth_lvl); } - fn print_pat(&mut self, pat: &Box>, depth_lvl: usize) { - let Pat { ty, span, kind } = &**pat; + fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) { + let &Pat { ty, span, ref kind } = pat; print_indented!(self, "Pat: {", depth_lvl); print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1); From 5742b9a5b51dc307a5a5afddd1c333329fd2d319 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 1 Feb 2025 17:47:51 +1100 Subject: [PATCH 2/6] Move THIR pattern traversal out of `Pat` and into `Thir` --- compiler/rustc_middle/src/thir.rs | 48 +++++++++++-------- .../src/builder/matches/mod.rs | 2 +- .../src/thir/pattern/check_match.rs | 11 +++-- compiler/rustc_pattern_analysis/src/rustc.rs | 5 +- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index d56046136c7a9..8d1a855c50922 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -647,11 +647,17 @@ impl<'tcx> Pat<'tcx> { _ => None, } } +} +impl<'tcx> Thir<'tcx> { /// Call `f` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` - pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) { - self.walk_always(|p| { + pub fn each_pat_binding( + &self, + pat: &Pat<'tcx>, + mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span), + ) { + self.walk_pat_always(pat, |p| { if let PatKind::Binding { name, mode, ty, .. } = p.kind { f(name, mode.0, ty, p.span); } @@ -661,17 +667,17 @@ impl<'tcx> Pat<'tcx> { /// Walk the pattern in left-to-right order. /// /// If `it(pat)` returns `false`, the children are not visited. - pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) { - self.walk_(&mut it) + pub fn walk_pat(&self, pat: &Pat<'tcx>, mut it: impl FnMut(&Pat<'tcx>) -> bool) { + self.walk_pat_inner(pat, &mut it); } - fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) { - if !it(self) { + fn walk_pat_inner(&self, pat: &Pat<'tcx>, it: &mut impl FnMut(&Pat<'tcx>) -> bool) { + if !it(pat) { return; } use PatKind::*; - match &self.kind { + match &pat.kind { Wild | Never | Range(..) @@ -682,22 +688,24 @@ impl<'tcx> Pat<'tcx> { | Binding { subpattern: Some(subpattern), .. } | Deref { subpattern } | DerefPattern { subpattern, .. } - | ExpandedConstant { subpattern, .. } => subpattern.walk_(it), + | ExpandedConstant { subpattern, .. } => self.walk_pat_inner(subpattern, it), Leaf { subpatterns } | Variant { subpatterns, .. } => { - subpatterns.iter().for_each(|field| field.pattern.walk_(it)) + subpatterns.iter().for_each(|field| self.walk_pat_inner(&field.pattern, it)) } - Or { pats } => pats.iter().for_each(|p| p.walk_(it)), + Or { pats } => pats.iter().for_each(|p| self.walk_pat_inner(p, it)), Array { box ref prefix, ref slice, box ref suffix } - | Slice { box ref prefix, ref slice, box ref suffix } => { - prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it)) - } + | Slice { box ref prefix, ref slice, box ref suffix } => prefix + .iter() + .chain(slice.iter()) + .chain(suffix.iter()) + .for_each(|p| self.walk_pat_inner(p, it)), } } /// Whether the pattern has a `PatKind::Error` nested within. - pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> { + pub fn pat_error_reported(&self, pat: &Pat<'tcx>) -> Result<(), ErrorGuaranteed> { let mut error = None; - self.walk(|pat| { + self.walk_pat(pat, |pat| { if let PatKind::Error(e) = pat.kind && error.is_none() { @@ -714,23 +722,23 @@ impl<'tcx> Pat<'tcx> { /// Walk the pattern in left-to-right order. /// /// If you always want to recurse, prefer this method over `walk`. - pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) { - self.walk(|p| { + pub fn walk_pat_always(&self, pat: &Pat<'tcx>, mut it: impl FnMut(&Pat<'tcx>)) { + self.walk_pat(pat, |p| { it(p); true }) } /// Whether this a never pattern. - pub fn is_never_pattern(&self) -> bool { + pub fn is_never_pattern(&self, pat: &Pat<'tcx>) -> bool { let mut is_never_pattern = false; - self.walk(|pat| match &pat.kind { + self.walk_pat(pat, |pat| match &pat.kind { PatKind::Never => { is_never_pattern = true; false } PatKind::Or { pats } => { - is_never_pattern = pats.iter().all(|p| p.is_never_pattern()); + is_never_pattern = pats.iter().all(|p| self.is_never_pattern(p)); false } _ => true, diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index b21ec8f3083b3..ff2dd68c99437 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -1012,7 +1012,7 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { span: pattern.span, bindings: Vec::new(), ascriptions: Vec::new(), - is_never: pattern.is_never_pattern(), + is_never: cx.thir.is_never_pattern(pattern), }; // Recursively remove irrefutable match pairs, while recording their // bindings/ascriptions, and sort or-patterns after other match pairs. diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 021edd5057150..b51b40b7b3263 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -278,14 +278,14 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { cx: &PatCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>, ) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> { - if let Err(err) = pat.pat_error_reported() { + if let Err(err) = cx.thir.pat_error_reported(pat) { self.error = Err(err); Err(err) } else { // Check the pattern for some things unrelated to exhaustiveness. let refutable = if cx.refutable { Refutable } else { Irrefutable }; let mut err = Ok(()); - pat.walk_always(|pat| { + cx.thir.walk_pat_always(pat, |pat| { check_borrow_conflicts_in_at_patterns(self, pat); check_for_bindings_named_same_as_variants(self, pat, refutable); err = err.and(check_never_pattern(cx, pat)); @@ -386,6 +386,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { scrutinee.map(|scrut| self.is_known_valid_scrutinee(scrut)).unwrap_or(true); PatCtxt { tcx: self.tcx, + thir: self.thir, typeck_results: self.typeck_results, typing_env: self.typing_env, module: self.tcx.parent_module(self.lint_level).to_def_id(), @@ -714,7 +715,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { && scrut.is_some() { let mut bindings = vec![]; - pat.each_binding(|name, _, _, _| bindings.push(name)); + self.thir.each_pat_binding(pat, |name, _, _, _| bindings.push(name)); let semi_span = span.shrink_to_hi(); let start_span = span.shrink_to_lo(); @@ -790,7 +791,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: ByRef::No if is_binding_by_move(ty) => { // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. let mut conflicts_ref = Vec::new(); - sub.each_binding(|_, mode, _, span| { + cx.thir.each_pat_binding(sub, |_, mode, _, span| { if matches!(mode, ByRef::Yes(_)) { conflicts_ref.push(span) } @@ -819,7 +820,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: let mut conflicts_move = Vec::new(); let mut conflicts_mut_mut = Vec::new(); let mut conflicts_mut_ref = Vec::new(); - sub.each_binding(|name, mode, ty, span| { + cx.thir.each_pat_binding(sub, |name, mode, ty, span| { match mode { ByRef::Yes(mut_inner) => match (mut_outer, mut_inner) { // Both sides are `ref`. diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 2694cf472f480..0b45c65bbca08 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId; use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::{self, Const}; -use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; +use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary, Thir}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, @@ -76,8 +76,9 @@ impl<'tcx> RevealedTy<'tcx> { } #[derive(Clone)] -pub struct RustcPatCtxt<'p, 'tcx: 'p> { +pub struct RustcPatCtxt<'p, 'tcx> { pub tcx: TyCtxt<'tcx>, + pub thir: &'p Thir<'tcx>, pub typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The module in which the match occurs. This is necessary for /// checking inhabited-ness of types because whether a type is (visibly) From 49194eb37f1f61b614520d4d45ab9d2d4ad752be Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 2 Feb 2025 15:58:43 +1100 Subject: [PATCH 3/6] Split up a complex subpattern match in `expr_into_pattern` --- .../src/builder/matches/mod.rs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index ff2dd68c99437..2b3dd1b622d80 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -604,19 +604,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Optimize the case of `let x: T = ...` to write directly // into `x` and then require that `T == typeof(x)`. PatKind::AscribeUserType { - subpattern: - box Pat { - kind: - PatKind::Binding { - mode: BindingMode(ByRef::No, _), - var, - subpattern: None, - .. - }, - .. - }, + ref subpattern, ascription: thir::Ascription { ref annotation, variance: _ }, - } => { + } if let PatKind::Binding { + mode: BindingMode(ByRef::No, _), + var, + subpattern: None, + .. + } = subpattern.kind => + { let place = self.storage_live_binding( block, var, From 02eb09ead59423bb1bad87b8f2a98e4793ab4fb1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 2 Feb 2025 16:21:52 +1100 Subject: [PATCH 4/6] !! (WIP) strip off AscribedUserType --- .../src/thir/pattern/check_match.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b51b40b7b3263..44eae5e48ae43 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -677,12 +677,12 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { let mut interpreted_as_const = None; let mut interpreted_as_const_sugg = None; - if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } - | PatKind::AscribeUserType { - subpattern: - box Pat { kind: PatKind::ExpandedConstant { def_id, is_inline: false, .. }, .. }, - .. - } = pat.kind + let mut subpat = pat; + while let PatKind::AscribeUserType { ref subpattern, .. } = subpat.kind { + subpat = subpattern; + } + + if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = subpat.kind && let DefKind::Const = self.tcx.def_kind(def_id) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) // We filter out paths with multiple path::segments. @@ -693,11 +693,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // When we encounter a constant as the binding name, point at the `const` definition. interpreted_as_const = Some(span); interpreted_as_const_sugg = Some(InterpretedAsConst { span: pat.span, variable }); - } else if let PatKind::Constant { .. } - | PatKind::AscribeUserType { - subpattern: box Pat { kind: PatKind::Constant { .. }, .. }, - .. - } = pat.kind + } else if let PatKind::Constant { .. } = subpat.kind && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) { // If the pattern to match is an integer literal: From 2d4bf4a15ecbc65250459fd62b4ae64b7ae2972a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 2 Feb 2025 16:23:38 +1100 Subject: [PATCH 5/6] !! (WIP) another match tweak --- compiler/rustc_ty_utils/src/consts.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 4038a1d68faec..cbe49d000b7d7 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -373,7 +373,8 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { match pat.kind { thir::PatKind::Constant { value } => value.has_non_region_param(), - thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => { + thir::PatKind::Range(ref range) => { + let &thir::PatRange { lo, hi, .. } = range.as_ref(); lo.has_non_region_param() || hi.has_non_region_param() } _ => false, From 0201b00be28176423658a0658893f1eceb2976ad Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 2 Feb 2025 16:40:22 +1100 Subject: [PATCH 6/6] !! (WIP) store THIR patterns in Arc instead of Box --- compiler/rustc_middle/src/thir.rs | 37 +++--- .../src/builder/matches/match_pair.rs | 28 +++-- .../src/builder/matches/mod.rs | 105 +++++++++--------- .../src/builder/matches/simplify.rs | 4 +- .../src/builder/matches/test.rs | 21 ++-- .../src/builder/matches/util.rs | 8 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 4 +- .../src/thir/pattern/check_match.rs | 12 +- .../src/thir/pattern/const_to_pat.rs | 13 ++- .../rustc_mir_build/src/thir/pattern/mod.rs | 46 ++++---- 11 files changed, 148 insertions(+), 134 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 8d1a855c50922..ccdc60ccca12f 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -11,6 +11,7 @@ use std::cmp::Ordering; use std::fmt; use std::ops::Index; +use std::sync::Arc; use rustc_abi::{FieldIdx, Integer, Size, VariantIdx}; use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece}; @@ -108,7 +109,7 @@ pub enum BodyTy<'tcx> { #[derive(Clone, Debug, HashStable)] pub struct Param<'tcx> { /// The pattern that appears in the parameter list, or None for implicit parameters. - pub pat: Option>>, + pub pat: Option>>, /// The possibly inferred type. pub ty: Ty<'tcx>, /// Span of the explicitly provided type, or None if inferred for closures. @@ -231,7 +232,7 @@ pub enum StmtKind<'tcx> { /// `let = ...` /// /// If a type annotation is included, it is added as an ascription pattern. - pattern: Box>, + pattern: Arc>, /// `let pat: ty = ` initializer: Option, @@ -379,7 +380,7 @@ pub enum ExprKind<'tcx> { /// (Not to be confused with [`StmtKind::Let`], which is a normal `let` statement.) Let { expr: ExprId, - pat: Box>, + pat: Arc>, }, /// A `match` expression. Match { @@ -571,7 +572,7 @@ pub struct FruInfo<'tcx> { /// A `match` arm. #[derive(Clone, Debug, HashStable)] pub struct Arm<'tcx> { - pub pattern: Box>, + pub pattern: Arc>, pub guard: Option, pub body: ExprId, pub lint_level: LintLevel, @@ -628,7 +629,7 @@ pub enum InlineAsmOperand<'tcx> { #[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct FieldPat<'tcx> { pub field: FieldIdx, - pub pattern: Box>, + pub pattern: Arc>, } #[derive(Clone, Debug, HashStable, TypeVisitable)] @@ -778,7 +779,7 @@ pub enum PatKind<'tcx> { AscribeUserType { ascription: Ascription<'tcx>, - subpattern: Box>, + subpattern: Arc>, }, /// `x`, `ref x`, `x @ P`, etc. @@ -789,7 +790,7 @@ pub enum PatKind<'tcx> { #[type_visitable(ignore)] var: LocalVarId, ty: Ty<'tcx>, - subpattern: Option>>, + subpattern: Option>>, /// Is this the leftmost occurrence of the binding, i.e., is `var` the /// `HirId` of this pattern? is_primary: bool, @@ -812,12 +813,12 @@ pub enum PatKind<'tcx> { /// `box P`, `&P`, `&mut P`, etc. Deref { - subpattern: Box>, + subpattern: Arc>, }, /// Deref pattern, written `box P` for now. DerefPattern { - subpattern: Box>, + subpattern: Arc>, mutability: hir::Mutability, }, @@ -851,31 +852,31 @@ pub enum PatKind<'tcx> { /// Otherwise, the actual pattern that the constant lowered to. As with /// other constants, inline constants are matched structurally where /// possible. - subpattern: Box>, + subpattern: Arc>, }, - Range(Box>), + Range(Arc>), /// Matches against a slice, checking the length and extracting elements. /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. /// e.g., `&[ref xs @ ..]`. Slice { - prefix: Box<[Box>]>, - slice: Option>>, - suffix: Box<[Box>]>, + prefix: Box<[Arc>]>, + slice: Option>>, + suffix: Box<[Arc>]>, }, /// Fixed match against an array; irrefutable. Array { - prefix: Box<[Box>]>, - slice: Option>>, - suffix: Box<[Box>]>, + prefix: Box<[Arc>]>, + slice: Option>>, + suffix: Box<[Arc>]>, }, /// An or-pattern, e.g. `p | q`. /// Invariant: `pats.len() >= 2`. Or { - pats: Box<[Box>]>, + pats: Box<[Arc>]>, }, /// A never pattern `!`. 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 9d59ffc88ba23..5907d34dd49f3 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use rustc_middle::mir::*; use rustc_middle::thir::{self, *}; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -12,11 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// [`PatKind::Leaf`]. /// /// Used internally by [`MatchPairTree::for_pattern`]. - fn field_match_pairs<'pat>( + fn field_match_pairs( &mut self, place: PlaceBuilder<'tcx>, - subpatterns: &'pat [FieldPat<'tcx>], - ) -> Vec> { + subpatterns: &[FieldPat<'tcx>], + ) -> Vec> { subpatterns .iter() .map(|fieldpat| { @@ -31,13 +33,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// array pattern or slice pattern, and adds those trees to `match_pairs`. /// /// Used internally by [`MatchPairTree::for_pattern`]. - fn prefix_slice_suffix<'pat>( + fn prefix_slice_suffix( &mut self, - match_pairs: &mut Vec>, + match_pairs: &mut Vec>, place: &PlaceBuilder<'tcx>, - prefix: &'pat [Box>], - opt_slice: &'pat Option>>, - suffix: &'pat [Box>], + prefix: &[Arc>], + opt_slice: &Option>>, + suffix: &[Arc>], ) { let tcx = self.tcx; 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> { } } -impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { +impl<'tcx> MatchPairTree<'tcx> { /// Recursively builds a match pair tree for the given pattern and its /// subpatterns. pub(in crate::builder) fn for_pattern( mut place_builder: PlaceBuilder<'tcx>, - pattern: &'pat Pat<'tcx>, + pattern: &Arc>, cx: &mut Builder<'_, 'tcx>, - ) -> MatchPairTree<'pat, 'tcx> { + ) -> MatchPairTree<'tcx> { + let pattern = Arc::clone(pattern); + // Force the place type to the pattern's type. // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks? if let Some(resolved) = place_builder.resolve_upvar(cx) { @@ -125,7 +129,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { if range.is_full_range(cx.tcx) == Some(true) { default_irrefutable() } else { - TestCase::Range(range) + TestCase::Range(Arc::clone(range)) } } diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 2b3dd1b622d80..662e8495c14bb 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -33,6 +33,7 @@ mod util; use std::assert_matches::assert_matches; use std::borrow::Borrow; use std::mem; +use std::sync::Arc; /// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded /// to recursive invocations. @@ -368,7 +369,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|arm| { let has_match_guard = if arm.guard.is_some() { HasMatchGuard::Yes } else { HasMatchGuard::No }; - (&*arm.pattern, has_match_guard) + (&arm.pattern, has_match_guard) }) .collect(); let built_tree = self.lower_match_tree( @@ -578,7 +579,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(super) fn expr_into_pattern( &mut self, mut block: BasicBlock, - irrefutable_pat: &Pat<'tcx>, + irrefutable_pat: &Arc>, initializer_id: ExprId, ) -> BlockAnd<()> { match irrefutable_pat.kind { @@ -668,7 +669,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn place_into_pattern( &mut self, block: BasicBlock, - irrefutable_pat: &Pat<'tcx>, + irrefutable_pat: &Arc>, initializer: PlaceBuilder<'tcx>, set_match_place: bool, ) -> BlockAnd<()> { @@ -985,21 +986,21 @@ impl<'tcx> PatternExtraData<'tcx> { /// /// Will typically be incorporated into a [`Candidate`]. #[derive(Debug, Clone)] -struct FlatPat<'pat, 'tcx> { +struct FlatPat<'tcx> { /// To match the pattern, all of these must be satisfied... // Invariant: all the match pairs are recursively simplified. // Invariant: or-patterns must be sorted to the end. - match_pairs: Vec>, + match_pairs: Vec>, extra_data: PatternExtraData<'tcx>, } -impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { +impl<'tcx> FlatPat<'tcx> { /// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest /// for the given pattern. fn new( place: PlaceBuilder<'tcx>, - pattern: &'pat Pat<'tcx>, + pattern: &Arc>, cx: &mut Builder<'_, 'tcx>, ) -> Self { // First, recursively build a tree of match pairs for the given pattern. @@ -1029,7 +1030,7 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { /// of candidates, where each "leaf" candidate represents one of the ways for /// the arm pattern to successfully match. #[derive(Debug)] -struct Candidate<'pat, 'tcx> { +struct Candidate<'tcx> { /// For the candidate to match, all of these must be satisfied... /// /// --- @@ -1051,7 +1052,7 @@ struct Candidate<'pat, 'tcx> { /// Invariants: /// - All [`TestCase::Irrefutable`] patterns have been removed by simplification. /// - All or-patterns ([`TestCase::Or`]) have been sorted to the end. - match_pairs: Vec>, + match_pairs: Vec>, /// ...and if this is non-empty, one of these subcandidates also has to match... /// @@ -1068,7 +1069,7 @@ struct Candidate<'pat, 'tcx> { /// Invariant: at the end of match tree lowering, this must not contain an /// `is_never` candidate, because that would break binding consistency. /// - See [`Builder::remove_never_subcandidates`]. - subcandidates: Vec>, + subcandidates: Vec>, /// ...and if there is a guard it must be evaluated; if it's `false` then branch to `otherwise_block`. /// @@ -1103,10 +1104,10 @@ struct Candidate<'pat, 'tcx> { false_edge_start_block: Option, } -impl<'tcx, 'pat> Candidate<'pat, 'tcx> { +impl<'tcx> Candidate<'tcx> { fn new( place: PlaceBuilder<'tcx>, - pattern: &'pat Pat<'tcx>, + pattern: &Arc>, has_guard: HasMatchGuard, cx: &mut Builder<'_, 'tcx>, ) -> Self { @@ -1119,7 +1120,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> { } /// Incorporates an already-simplified [`FlatPat`] into a new candidate. - fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self { + fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self { Candidate { match_pairs: flat_pat.match_pairs, extra_data: flat_pat.extra_data, @@ -1168,7 +1169,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> { /// reference or by value, and to allow a mutable "context" to be shared by the /// traversal callbacks. Most traversals can use the simpler /// [`Candidate::visit_leaves`] wrapper instead. -fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>( +fn traverse_candidate<'tcx, C, T, I>( candidate: C, context: &mut T, // Called when visiting a "leaf" candidate (with no subcandidates). @@ -1180,7 +1181,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>( // Called after visiting a "node" candidate's children. complete_children: impl Copy + Fn(&mut T), ) where - C: Borrow>, // Typically `Candidate` or `&mut Candidate` + C: Borrow>, // Typically `Candidate` or `&mut Candidate` I: Iterator, { if candidate.borrow().subcandidates.is_empty() { @@ -1230,20 +1231,20 @@ struct Ascription<'tcx> { /// participate in or-pattern expansion, where they are transformed into subcandidates. /// - See [`Builder::expand_and_match_or_candidates`]. #[derive(Debug, Clone)] -enum TestCase<'pat, 'tcx> { +enum TestCase<'tcx> { Irrefutable { binding: Option>, ascription: Option> }, Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx }, Constant { value: mir::Const<'tcx> }, - Range(&'pat PatRange<'tcx>), + Range(Arc>), Slice { len: usize, variable_length: bool }, Deref { temp: Place<'tcx>, mutability: Mutability }, Never, - Or { pats: Box<[FlatPat<'pat, 'tcx>]> }, + Or { pats: Box<[FlatPat<'tcx>]> }, } -impl<'pat, 'tcx> TestCase<'pat, 'tcx> { - fn as_range(&self) -> Option<&'pat PatRange<'tcx>> { - if let Self::Range(v) = self { Some(*v) } else { None } +impl<'tcx> TestCase<'tcx> { + fn as_range(&self) -> Option<&PatRange<'tcx>> { + if let Self::Range(v) = self { Some(v.as_ref()) } else { None } } } @@ -1253,7 +1254,7 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> { /// Each node also has a list of subpairs (possibly empty) that must also match, /// and a reference to the THIR pattern it represents. #[derive(Debug, Clone)] -pub(crate) struct MatchPairTree<'pat, 'tcx> { +pub(crate) struct MatchPairTree<'tcx> { /// This place... /// /// --- @@ -1268,7 +1269,7 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> { /// --- /// Invariant: after creation and simplification in [`FlatPat::new`], /// this must not be [`TestCase::Irrefutable`]. - test_case: TestCase<'pat, 'tcx>, + test_case: TestCase<'tcx>, /// ... and these subpairs must match. /// @@ -1280,7 +1281,7 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> { subpairs: Vec, /// The pattern this was created from. - pattern: &'pat Pat<'tcx>, + pattern: Arc>, } /// See [`Test`] for more. @@ -1316,7 +1317,7 @@ enum TestKind<'tcx> { }, /// Test whether the value falls within an inclusive or exclusive range. - Range(Box>), + Range(Arc>), /// Test that the length of the slice is `== len` or `>= len`. Len { len: u64, op: BinOp }, @@ -1419,7 +1420,7 @@ struct BuiltMatchTree<'tcx> { impl<'tcx> MatchTreeSubBranch<'tcx> { fn from_sub_candidate( - candidate: Candidate<'_, 'tcx>, + candidate: Candidate<'tcx>, parent_data: &Vec>, ) -> Self { debug_assert!(candidate.match_pairs.is_empty()); @@ -1445,12 +1446,12 @@ impl<'tcx> MatchTreeSubBranch<'tcx> { } impl<'tcx> MatchTreeBranch<'tcx> { - fn from_candidate(candidate: Candidate<'_, 'tcx>) -> Self { + fn from_candidate(candidate: Candidate<'tcx>) -> Self { let mut sub_branches = Vec::new(); traverse_candidate( candidate, &mut Vec::new(), - &mut |candidate: Candidate<'_, '_>, parent_data: &mut Vec>| { + &mut |candidate: Candidate<'_>, parent_data: &mut Vec>| { sub_branches.push(MatchTreeSubBranch::from_sub_candidate(candidate, parent_data)); }, |inner_candidate, parent_data| { @@ -1487,7 +1488,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scrutinee_span: Span, scrutinee_place_builder: &PlaceBuilder<'tcx>, match_start_span: Span, - patterns: Vec<(&'pat Pat<'tcx>, HasMatchGuard)>, + patterns: Vec<(&Arc>, HasMatchGuard)>, refutable: bool, ) -> BuiltMatchTree<'tcx> where @@ -1497,7 +1498,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // input patterns, but other parts of match lowering also introduce subcandidates (for // sub-or-patterns). So inside the algorithm, the candidates list may not correspond to // match arms directly. - let mut candidates: Vec> = patterns + let mut candidates: Vec> = patterns .into_iter() .map(|(pat, has_guard)| { Candidate::new(scrutinee_place_builder.clone(), pat, has_guard, self) @@ -1660,7 +1661,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, scrutinee_span: Span, start_block: BasicBlock, - candidates: &mut [&mut Candidate<'_, 'tcx>], + candidates: &mut [&mut Candidate<'tcx>], ) -> BasicBlock { ensure_sufficient_stack(|| { self.match_candidates_inner(span, scrutinee_span, start_block, candidates) @@ -1674,7 +1675,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, scrutinee_span: Span, mut start_block: BasicBlock, - candidates: &mut [&mut Candidate<'_, 'tcx>], + candidates: &mut [&mut Candidate<'tcx>], ) -> BasicBlock { if let [first, ..] = candidates { if first.false_edge_start_block.is_none() { @@ -1743,7 +1744,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// [otherwise block]: Candidate::otherwise_block fn select_matched_candidate( &mut self, - candidate: &mut Candidate<'_, 'tcx>, + candidate: &mut Candidate<'tcx>, start_block: BasicBlock, ) -> BasicBlock { assert!(candidate.otherwise_block.is_none()); @@ -1761,13 +1762,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Takes a list of candidates such that some of the candidates' first match pairs are /// or-patterns. This expands as many or-patterns as possible and processes the resulting /// candidates. Returns the unprocessed candidates if any. - fn expand_and_match_or_candidates<'pat, 'b, 'c>( + fn expand_and_match_or_candidates<'b, 'c>( &mut self, span: Span, scrutinee_span: Span, start_block: BasicBlock, - candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], - ) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> { + candidates: &'b mut [&'c mut Candidate<'tcx>], + ) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> { // We can't expand or-patterns freely. The rule is: // - If a candidate doesn't start with an or-pattern, we include it in // the expansion list as-is (i.e. it "expands" to itself). @@ -1861,10 +1862,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new /// subcandidate. Any candidate that has been expanded this way should also be postprocessed /// at the end of [`Self::expand_and_match_or_candidates`]. - fn create_or_subcandidates<'pat>( + fn create_or_subcandidates( &mut self, - candidate: &mut Candidate<'pat, 'tcx>, - match_pair: MatchPairTree<'pat, 'tcx>, + candidate: &mut Candidate<'tcx>, + match_pair: MatchPairTree<'tcx>, ) { let TestCase::Or { pats } = match_pair.test_case else { bug!() }; debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats); @@ -1934,7 +1935,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// /// Note that this takes place _after_ the subcandidates have participated /// in match tree lowering. - fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) { + fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) { assert!(!candidate.subcandidates.is_empty()); if candidate.has_guard { // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard. @@ -1977,7 +1978,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Never subcandidates may have a set of bindings inconsistent with their siblings, /// which would break later code. So we filter them out. Note that we can't filter out /// top-level candidates this way. - fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) { + fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) { if candidate.subcandidates.is_empty() { return; } @@ -2016,7 +2017,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, span: Span, scrutinee_span: Span, - candidate: &mut Candidate<'_, 'tcx>, + candidate: &mut Candidate<'tcx>, ) { if candidate.match_pairs.is_empty() { return; @@ -2082,7 +2083,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// [`Switch`]: TestKind::Switch /// [`SwitchInt`]: TestKind::SwitchInt /// [`Range`]: TestKind::Range - fn pick_test(&mut self, candidates: &[&mut Candidate<'_, 'tcx>]) -> (Place<'tcx>, Test<'tcx>) { + fn pick_test(&mut self, candidates: &[&mut Candidate<'tcx>]) -> (Place<'tcx>, Test<'tcx>) { // Extract the match-pair from the highest priority candidate let match_pair = &candidates[0].match_pairs[0]; let test = self.pick_test_for_match_pair(match_pair); @@ -2133,18 +2134,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// The sorted candidates are mutated to remove entailed match pairs: /// - candidate 0 becomes `[z @ true]` since we know that `x` was `true`; /// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`. - fn sort_candidates<'b, 'c, 'pat>( + fn sort_candidates<'b, 'c>( &mut self, match_place: Place<'tcx>, test: &Test<'tcx>, - mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], + mut candidates: &'b mut [&'c mut Candidate<'tcx>], ) -> ( - &'b mut [&'c mut Candidate<'pat, 'tcx>], - FxIndexMap, Vec<&'b mut Candidate<'pat, 'tcx>>>, + &'b mut [&'c mut Candidate<'tcx>], + FxIndexMap, Vec<&'b mut Candidate<'tcx>>>, ) { // For each of the possible outcomes, collect vector of candidates that apply if the test // has that particular outcome. - let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default(); + let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_>>> = Default::default(); let total_candidate_count = candidates.len(); @@ -2270,13 +2271,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// ``` /// /// We return the unprocessed candidates. - fn test_candidates<'pat, 'b, 'c>( + fn test_candidates<'b, 'c>( &mut self, span: Span, scrutinee_span: Span, - candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], + candidates: &'b mut [&'c mut Candidate<'tcx>], start_block: BasicBlock, - ) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> { + ) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> { // Choose a match pair from the first candidate, and use it to determine a // test to perform that will confirm or refute that match pair. let (match_place, test) = self.pick_test(candidates); @@ -2339,7 +2340,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, expr_id: ExprId, - pat: &Pat<'tcx>, + pat: &Arc>, source_scope: Option, scope_span: Span, declare_let_bindings: DeclareLetBindings, diff --git a/compiler/rustc_mir_build/src/builder/matches/simplify.rs b/compiler/rustc_mir_build/src/builder/matches/simplify.rs index ebaed1e431bbc..15c860151dc9e 100644 --- a/compiler/rustc_mir_build/src/builder/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/builder/matches/simplify.rs @@ -23,9 +23,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and /// ascriptions in `extra_data`. #[instrument(skip(self), level = "debug")] - pub(super) fn simplify_match_pairs<'pat>( + pub(super) fn simplify_match_pairs( &mut self, - match_pairs: &mut Vec>, + match_pairs: &mut Vec>, extra_data: &mut PatternExtraData<'tcx>, ) { // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index afe6b4475be3c..40a5f79822f5b 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -6,6 +6,7 @@ // the candidates based on the result. use std::cmp::Ordering; +use std::sync::Arc; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; @@ -26,9 +27,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// /// It is a bug to call this with a not-fully-simplified pattern. - pub(super) fn pick_test_for_match_pair<'pat>( + pub(super) fn pick_test_for_match_pair( &mut self, - match_pair: &MatchPairTree<'pat, 'tcx>, + match_pair: &MatchPairTree<'tcx>, ) -> Test<'tcx> { let kind = match match_pair.test_case { TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def }, @@ -37,9 +38,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt, TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty }, - TestCase::Range(range) => { + TestCase::Range(ref range) => { assert_eq!(range.ty, match_pair.pattern.ty); - TestKind::Range(Box::new(range.clone())) + TestKind::Range(Arc::clone(range)) } TestCase::Slice { len, variable_length } => { @@ -521,8 +522,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, test_place: Place<'tcx>, test: &Test<'tcx>, - candidate: &mut Candidate<'_, 'tcx>, - sorted_candidates: &FxIndexMap, Vec<&mut Candidate<'_, 'tcx>>>, + candidate: &mut Candidate<'tcx>, + sorted_candidates: &FxIndexMap, Vec<&mut Candidate<'tcx>>>, ) -> Option> { // Find the match_pair for this place (if any). At present, // afaik, there can be at most one. (In the future, if we @@ -565,7 +566,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // a new value might invalidate that property for range patterns that // have already been sorted into the failure arm, so we must take care // not to add such values here. - let is_covering_range = |test_case: &TestCase<'_, 'tcx>| { + let is_covering_range = |test_case: &TestCase<'tcx>| { test_case.as_range().is_some_and(|range| { matches!( range.contains(value, self.tcx, self.typing_env()), @@ -573,7 +574,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) }) }; - let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| { + let is_conflicting_candidate = |candidate: &&mut Candidate<'tcx>| { candidate .match_pairs .iter() @@ -685,8 +686,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - (TestKind::Range(test), &TestCase::Range(pat)) => { - if test.as_ref() == pat { + (TestKind::Range(test), TestCase::Range(pat)) => { + if test == pat { fully_matched = true; Some(TestBranch::Success) } else { diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs index 1bd399e511b39..83e79572b2a8e 100644 --- a/compiler/rustc_mir_build/src/builder/matches/util.rs +++ b/compiler/rustc_mir_build/src/builder/matches/util.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// a MIR pass run after borrow checking. pub(super) fn collect_fake_borrows<'tcx>( cx: &mut Builder<'_, 'tcx>, - candidates: &[Candidate<'_, 'tcx>], + candidates: &[Candidate<'tcx>], temp_span: Span, scrutinee_base: PlaceBase, ) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> { @@ -135,7 +135,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } } - fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) { + fn visit_candidate(&mut self, candidate: &Candidate<'tcx>) { for binding in &candidate.extra_data.bindings { self.visit_binding(binding); } @@ -144,7 +144,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } } - fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) { + fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'tcx>) { for binding in &flat_pat.extra_data.bindings { self.visit_binding(binding); } @@ -153,7 +153,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } } - fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) { + fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'tcx>) { if let TestCase::Or { pats, .. } = &match_pair.test_case { for flat_pat in pats.iter() { self.visit_flat_pat(flat_pat) diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index c9df027687ab9..7a1b76a3db3f6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use rustc_hir as hir; use rustc_index::Idx; use rustc_middle::middle::region; @@ -86,7 +88,7 @@ impl<'tcx> Cx<'tcx> { span: ty.span, inferred_ty: self.typeck_results.node_type(ty.hir_id), }; - pattern = Box::new(Pat { + pattern = Arc::new(Pat { ty: pattern.ty, span: pattern.span, kind: PatKind::AscribeUserType { diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index a98c2bb61f666..c9472c31934c1 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -2,6 +2,8 @@ //! structures into the THIR. The `builder` is generally ignorant of the tcx, //! etc., and instead goes through the `Cx` for most of its work. +use std::sync::Arc; + use rustc_data_structures::steal::Steal; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -112,7 +114,7 @@ impl<'tcx> Cx<'tcx> { } #[instrument(level = "debug", skip(self))] - fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box> { + fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Arc> { pat_from_hir(self.tcx, self.typing_env, self.typeck_results(), p) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 44eae5e48ae43..0b6b98a371685 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -62,7 +62,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err }; for param in thir.params.iter() { - if let Some(box ref pattern) = param.pat { + if let Some(ref pattern) = param.pat { visitor.check_binding_is_irrefutable(pattern, origin, None, None); } } @@ -155,7 +155,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => { self.check_match(scrutinee, arms, match_source, ex.span); } - ExprKind::Let { box ref pat, expr } => { + ExprKind::Let { ref pat, expr } => { self.check_let(pat, Some(expr), ex.span); } ExprKind::LogicalOp { op: LogicalOp::And, .. } @@ -176,9 +176,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { fn visit_stmt(&mut self, stmt: &'p Stmt<'tcx>) { match stmt.kind { - StmtKind::Let { - box ref pattern, initializer, else_block, lint_level, span, .. - } => { + StmtKind::Let { ref pattern, initializer, else_block, lint_level, span, .. } => { self.with_lint_level(lint_level, |this| { let let_source = if else_block.is_some() { LetSource::LetElse } else { LetSource::PlainLet }; @@ -257,7 +255,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { ExprKind::Scope { value, lint_level, .. } => { self.with_lint_level(lint_level, |this| this.visit_land_rhs(&this.thir[value])) } - ExprKind::Let { box ref pat, expr } => { + ExprKind::Let { ref pat, expr } => { let expr = &self.thir()[expr]; self.with_let_source(LetSource::None, |this| { this.visit_expr(expr); @@ -774,7 +772,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { /// This analysis is *not* subsumed by NLL. fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: &Pat<'tcx>) { // Extract `sub` in `binding @ sub`. - let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { + let PatKind::Binding { name, mode, ty, subpattern: Some(ref sub), .. } = pat.kind else { return; }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index cc6d69710e4c2..35253eaa670c1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,4 +1,5 @@ use core::ops::ControlFlow; +use std::sync::Arc; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; @@ -41,7 +42,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ty: Ty<'tcx>, id: hir::HirId, span: Span, - ) -> Box> { + ) -> Arc> { let mut convert = ConstToPat::new(self, id, span, c); match c.kind() { @@ -84,7 +85,7 @@ impl<'tcx> ConstToPat<'tcx> { } /// We errored. Signal that in the pattern, so that follow up errors can be silenced. - fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box> { + fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Arc> { if let ty::ConstKind::Unevaluated(uv) = self.c.kind() { let def_kind = self.tcx.def_kind(uv.def); if let hir::def::DefKind::AssocConst = def_kind @@ -100,14 +101,14 @@ impl<'tcx> ConstToPat<'tcx> { ); } } - Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()) }) + Arc::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()) }) } fn unevaluated_to_pat( &mut self, uv: ty::UnevaluatedConst<'tcx>, ty: Ty<'tcx>, - ) -> Box> { + ) -> Arc> { trace!(self.treat_byte_string_as_slice); // It's not *technically* correct to be revealing opaque types here as borrowcheck has @@ -216,7 +217,7 @@ impl<'tcx> ConstToPat<'tcx> { // Recursive helper for `to_pat`; invoke that (instead of calling this directly). // FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately. #[instrument(skip(self), level = "debug")] - fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box> { + fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Arc> { let span = self.span; let tcx = self.tcx; let kind = match ty.kind() { @@ -363,7 +364,7 @@ impl<'tcx> ConstToPat<'tcx> { } }; - Box::new(Pat { span, ty, kind }) + Arc::new(Pat { span, ty, kind }) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 20a728d6d5b2c..a2ce345e1138f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -4,6 +4,7 @@ mod check_match; mod const_to_pat; use std::cmp::Ordering; +use std::sync::Arc; use rustc_abi::{FieldIdx, Integer}; use rustc_errors::MultiSpan; @@ -43,7 +44,7 @@ pub(super) fn pat_from_hir<'a, 'tcx>( typing_env: ty::TypingEnv<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, -) -> Box> { +) -> Arc> { let mut pcx = PatCtxt { tcx, typing_env, @@ -89,7 +90,7 @@ pub(super) fn pat_from_hir<'a, 'tcx>( } impl<'a, 'tcx> PatCtxt<'a, 'tcx> { - fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { + fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Arc> { // When implicit dereferences have been inserted in this pattern, the unadjusted lowered // pattern has the type that results *after* dereferencing. For example, in this code: // @@ -122,7 +123,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| { debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty); - Box::new(Pat { + Arc::new(Pat { span: thir_pat.span, ty: *ref_ty, kind: PatKind::Deref { subpattern: thir_pat }, @@ -164,12 +165,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Some(expr) => { let (kind, ascr, inline_const) = match self.lower_lit(expr) { PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) + let kind = Arc::unwrap_or_clone(subpattern).kind; + (kind, None, def_id.as_local()) } PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) + let kind = Arc::unwrap_or_clone(subpattern).kind; + (kind, None, None) } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { + PatKind::AscribeUserType { ascription, subpattern } => { + let kind = Arc::unwrap_or_clone(subpattern).kind; (kind, Some(ascription), None) } kind => (kind, None, None), @@ -260,7 +264,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env); - let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); + let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty })); match (end, cmp) { // `x..y` where `x < y`. (RangeEnd::Excluded, Some(Ordering::Less)) => {} @@ -301,21 +305,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { for ascription in [lo_ascr, hi_ascr].into_iter().flatten() { kind = PatKind::AscribeUserType { ascription, - subpattern: Box::new(Pat { span, ty, kind }), + subpattern: Arc::new(Pat { span, ty, kind }), }; } for def in [lo_inline, hi_inline].into_iter().flatten() { kind = PatKind::ExpandedConstant { def_id: def.to_def_id(), is_inline: true, - subpattern: Box::new(Pat { span, ty, kind }), + subpattern: Arc::new(Pat { span, ty, kind }), }; } Ok(kind) } #[instrument(skip(self), level = "debug")] - fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { + fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Arc> { let mut ty = self.typeck_results.node_type(pat.hir_id); let mut span = pat.span; @@ -426,12 +430,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) }, // FIXME(guard_patterns): implement guard pattern lowering - hir::PatKind::Guard(pat, _) => self.lower_pattern(pat).kind, + hir::PatKind::Guard(pat, _) => Arc::unwrap_or_clone(self.lower_pattern(pat)).kind, hir::PatKind::Err(guar) => PatKind::Error(guar), }; - Box::new(Pat { span, ty, kind }) + Arc::new(Pat { span, ty, kind }) } fn lower_tuple_subpats( @@ -449,11 +453,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .collect() } - fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box>]> { + fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Arc>]> { pats.iter().map(|p| self.lower_pattern(p)).collect() } - fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option>> { + fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option>> { pat.map(|p| self.lower_pattern(p)) } @@ -562,7 +566,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { inferred_ty: self.typeck_results.node_type(hir_id), }; kind = PatKind::AscribeUserType { - subpattern: Box::new(Pat { span, ty, kind }), + subpattern: Arc::new(Pat { span, ty, kind }), ascription: Ascription { annotation, variance: ty::Covariant }, }; } @@ -574,11 +578,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// it to `const_to_pat`. Any other path (like enum variants without fields) /// is converted to the corresponding pattern via `lower_variant_or_leaf`. #[instrument(skip(self), level = "debug")] - fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Box> { + fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Arc> { let ty = self.typeck_results.node_type(id); let res = self.typeck_results.qpath_res(qpath, id); - let pat_from_kind = |kind| Box::new(Pat { span, ty, kind }); + let pat_from_kind = |kind| Arc::new(Pat { span, ty, kind }); let (def_id, is_associated_const) = match res { Res::Def(DefKind::Const, def_id) => (def_id, false), @@ -590,7 +594,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let args = self.typeck_results.node_args(id); let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args }); let subpattern = self.const_to_pat(c, ty, id, span); - let pattern = Box::new(Pat { + let pattern = Arc::new(Pat { span, ty, kind: PatKind::ExpandedConstant { subpattern, def_id, is_inline: false }, @@ -607,7 +611,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { span, inferred_ty: self.typeck_results().node_type(id), }; - Box::new(Pat { + Arc::new(Pat { span, kind: PatKind::AscribeUserType { subpattern: pattern, @@ -655,7 +659,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> { let (lit, neg) = match &expr.kind { hir::PatExprKind::Path(qpath) => { - return self.lower_path(qpath, expr.hir_id, expr.span).kind; + return Arc::unwrap_or_clone(self.lower_path(qpath, expr.hir_id, expr.span)).kind; } hir::PatExprKind::ConstBlock(anon_const) => { return self.lower_inline_const(anon_const, expr.hir_id, expr.span); @@ -666,7 +670,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ct_ty = self.typeck_results.node_type(expr.hir_id); let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; let constant = self.tcx.at(expr.span).lit_to_const(lit_input); - self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind + Arc::unwrap_or_clone(self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span)).kind } }