From 053874eecc9806f36195c35a7fad9c8878b0788e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 25 Aug 2022 12:25:44 +1000 Subject: [PATCH 1/5] Clean up THIR patterns. `thir::Pat::kind` is a `Box`, which doesn't follow the usual pattern in AST/HIR/THIR which is that the "kind" enum for a node is stored inline within the parent struct. This commit makes the `PatKind` directly inline within the `Pat`. This requires using `Box` in all the types that hold a `Pat. Ideally, `Pat` would be stored in `Thir` like `Expr` and `Stmt` and referred to with a `PatId` rather than `Box`. But this is hard to do because lots of `Pat`s get created after the destruction of the `Cx` that does normal THIR building. But this does get us a step closer to `PatId`, because all the `Box` occurrences would be replaced with `PatId` if `PatId` ever happened. At 128 bytes, `Pat` is large. Subsequent commits will shrink it. --- compiler/rustc_middle/src/thir.rs | 48 +++++++++---------- compiler/rustc_middle/src/thir/visit.rs | 4 +- compiler/rustc_mir_build/src/build/block.rs | 4 +- .../rustc_mir_build/src/build/matches/mod.rs | 21 ++++---- .../src/build/matches/simplify.rs | 14 +++--- .../rustc_mir_build/src/build/matches/test.rs | 20 ++++---- .../rustc_mir_build/src/build/matches/util.rs | 6 +-- compiler/rustc_mir_build/src/build/mod.rs | 4 +- .../rustc_mir_build/src/check_unsafety.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 8 ++-- compiler/rustc_mir_build/src/thir/cx/mod.rs | 2 +- .../src/thir/pattern/const_to_pat.rs | 34 ++++++------- .../src/thir/pattern/deconstruct_pat.rs | 26 +++++----- .../rustc_mir_build/src/thir/pattern/mod.rs | 47 +++++++++--------- compiler/rustc_ty_utils/src/consts.rs | 2 +- 15 files changed, 123 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 0f2504e3d9afe..99d72f70ba68a 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -180,7 +180,7 @@ pub enum StmtKind<'tcx> { /// `let = ...` /// /// If a type annotation is included, it is added as an ascription pattern. - pattern: Pat<'tcx>, + pattern: Box>, /// `let pat: ty = ` initializer: Option, @@ -301,7 +301,7 @@ pub enum ExprKind<'tcx> { }, Let { expr: ExprId, - pat: Pat<'tcx>, + pat: Box>, }, /// A `match` expression. Match { @@ -467,7 +467,7 @@ pub struct FruInfo<'tcx> { /// A `match` arm. #[derive(Clone, Debug, HashStable)] pub struct Arm<'tcx> { - pub pattern: Pat<'tcx>, + pub pattern: Box>, pub guard: Option>, pub body: ExprId, pub lint_level: LintLevel, @@ -479,7 +479,7 @@ pub struct Arm<'tcx> { #[derive(Clone, Debug, HashStable)] pub enum Guard<'tcx> { If(ExprId), - IfLet(Pat<'tcx>, ExprId), + IfLet(Box>, ExprId), } #[derive(Copy, Clone, Debug, HashStable)] @@ -534,19 +534,19 @@ pub enum BindingMode { #[derive(Clone, Debug, HashStable)] pub struct FieldPat<'tcx> { pub field: Field, - pub pattern: Pat<'tcx>, + pub pattern: Box>, } #[derive(Clone, Debug, HashStable)] pub struct Pat<'tcx> { pub ty: Ty<'tcx>, pub span: Span, - pub kind: Box>, + pub kind: PatKind<'tcx>, } impl<'tcx> Pat<'tcx> { pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self { - Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) } + Pat { ty, span: DUMMY_SP, kind: PatKind::Wild } } } @@ -581,7 +581,7 @@ pub enum PatKind<'tcx> { AscribeUserType { ascription: Ascription<'tcx>, - subpattern: Pat<'tcx>, + subpattern: Box>, }, /// `x`, `ref x`, `x @ P`, etc. @@ -591,7 +591,7 @@ pub enum PatKind<'tcx> { mode: BindingMode, 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, @@ -614,7 +614,7 @@ pub enum PatKind<'tcx> { /// `box P`, `&P`, `&mut P`, etc. Deref { - subpattern: Pat<'tcx>, + subpattern: Box>, }, /// One of the following: @@ -634,22 +634,22 @@ pub enum PatKind<'tcx> { /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. /// e.g., `&[ref xs @ ..]`. Slice { - prefix: Vec>, - slice: Option>, - suffix: Vec>, + prefix: Vec>>, + slice: Option>>, + suffix: Vec>>, }, /// Fixed match against an array; irrefutable. Array { - prefix: Vec>, - slice: Option>, - suffix: Vec>, + prefix: Vec>>, + slice: Option>>, + suffix: Vec>>, }, /// An or-pattern, e.g. `p | q`. /// Invariant: `pats.len() >= 2`. Or { - pats: Vec>, + pats: Vec>>, }, } @@ -674,7 +674,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { }; let mut start_or_comma = || start_or_continue(", "); - match *self.kind { + match self.kind { PatKind::Wild => write!(f, "_"), PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern), PatKind::Binding { mutability, name, mode, ref subpattern, .. } => { @@ -695,7 +695,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { Ok(()) } PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => { - let variant = match *self.kind { + let variant = match self.kind { PatKind::Variant { adt_def, variant_index, .. } => { Some(adt_def.variant(variant_index)) } @@ -714,7 +714,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { let mut printed = 0; for p in subpatterns { - if let PatKind::Wild = *p.pattern.kind { + if let PatKind::Wild = p.pattern.kind { continue; } let name = variant.fields[p.field.index()].name; @@ -780,7 +780,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } if let Some(ref slice) = *slice { write!(f, "{}", start_or_comma())?; - match *slice.kind { + match slice.kind { PatKind::Wild => {} _ => write!(f, "{}", slice)?, } @@ -809,8 +809,8 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); - static_assert_size!(Pat<'_>, 24); + static_assert_size!(Pat<'_>, 128); static_assert_size!(PatKind<'_>, 112); - static_assert_size!(Stmt<'_>, 72); - static_assert_size!(StmtKind<'_>, 64); + static_assert_size!(Stmt<'_>, 56); + static_assert_size!(StmtKind<'_>, 48); } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index c5c48a6360925..5168c2120f43d 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -211,7 +211,7 @@ pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<' pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) { use PatKind::*; - match pat.kind.as_ref() { + match &pat.kind { AscribeUserType { subpattern, ascription: _ } | Deref { subpattern } | Binding { @@ -236,7 +236,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' visitor.visit_pat(&subpattern); } if let Some(pat) = slice { - visitor.visit_pat(pat); + visitor.visit_pat(&pat); } for subpattern in suffix { visitor.visit_pat(&subpattern); diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index d5213dc0e0467..ef976d6308b50 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -117,7 +117,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { lint_level, else_block, } => { - let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild); + let ignores_expr_result = matches!(pattern.kind, PatKind::Wild); this.block_context.push(BlockFrame::Statement { ignores_expr_result }); // Enter the remainder scope, i.e., the bindings' destruction scope. @@ -160,7 +160,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ArmHasGuard(false), Some((None, initializer_span)), ); - this.expr_into_pattern(block, pattern.clone(), init) // irrefutable pattern + this.expr_into_pattern(block, (**pattern).clone(), init) // irrefutable pattern } }) }, diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 0e5cd6199ac9f..72f8034bbc176 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -493,7 +493,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { irrefutable_pat: Pat<'tcx>, initializer: &Expr<'tcx>, ) -> BlockAnd<()> { - match *irrefutable_pat.kind { + match irrefutable_pat.kind { // Optimize the case of `let x = ...` to write directly into `x` PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => { let place = @@ -518,13 +518,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // broken. PatKind::AscribeUserType { subpattern: - Pat { + box Pat { kind: - box PatKind::Binding { - mode: BindingMode::ByValue, - var, - subpattern: None, - .. + PatKind::Binding { + mode: BindingMode::ByValue, var, subpattern: None, .. }, .. }, @@ -744,7 +741,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { "visit_primary_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty ); - match *pattern.kind { + match pattern.kind { PatKind::Binding { mutability, name, @@ -1330,7 +1327,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // All of the or-patterns have been sorted to the end, so if the first // pattern is an or-pattern we only have or-patterns. - match *first_candidate.match_pairs[0].pattern.kind { + match first_candidate.match_pairs[0].pattern.kind { PatKind::Or { .. } => (), _ => { self.test_candidates( @@ -1350,7 +1347,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut otherwise = None; for match_pair in match_pairs { - let PatKind::Or { ref pats } = &*match_pair.pattern.kind else { + let PatKind::Or { ref pats } = &match_pair.pattern.kind else { bug!("Or-patterns should have been sorted to the end"); }; let or_span = match_pair.pattern.span; @@ -1384,7 +1381,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: &mut Candidate<'pat, 'tcx>, otherwise: &mut Option, - pats: &'pat [Pat<'tcx>], + pats: &'pat [Box>], or_span: Span, place: PlaceBuilder<'tcx>, fake_borrows: &mut Option>>, @@ -2289,7 +2286,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let else_block_span = self.thir[else_block].span; let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| { let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span)); - let pat = Pat { ty: init.ty, span: else_block_span, kind: Box::new(PatKind::Wild) }; + let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild }; let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false); this.declare_bindings( visibility_scope, diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index c6298904140c3..b9954be377b36 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { loop { let match_pairs = mem::take(&mut candidate.match_pairs); - if let [MatchPair { pattern: Pat { kind: box PatKind::Or { pats }, .. }, place }] = + if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = &*match_pairs { existing_bindings.extend_from_slice(&new_bindings); @@ -113,7 +113,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // late as possible. candidate .match_pairs - .sort_by_key(|pair| matches!(*pair.pattern.kind, PatKind::Or { .. })); + .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. })); debug!(simplified = ?candidate, "simplify_candidate"); return false; // if we were not able to simplify any, done. } @@ -127,10 +127,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: &Candidate<'pat, 'tcx>, place: PlaceBuilder<'tcx>, - pats: &'pat [Pat<'tcx>], + pats: &'pat [Box>], ) -> Vec> { pats.iter() - .map(|pat| { + .map(|box pat| { let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard); self.simplify_candidate(&mut candidate); candidate @@ -149,7 +149,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate: &mut Candidate<'pat, 'tcx>, ) -> Result<(), MatchPair<'pat, 'tcx>> { let tcx = self.tcx; - match *match_pair.pattern.kind { + match match_pair.pattern.kind { PatKind::AscribeUserType { ref subpattern, ascription: thir::Ascription { ref annotation, variance }, @@ -254,7 +254,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut candidate.match_pairs, &match_pair.place, prefix, - slice.as_ref(), + slice, suffix, ); Ok(()) @@ -294,7 +294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut candidate.match_pairs, &match_pair.place, prefix, - slice.as_ref(), + slice, suffix, ); Ok(()) diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 598da80c574af..ce85f240603a8 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -29,7 +29,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// /// It is a bug to call this with a not-fully-simplified pattern. pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { - match *match_pair.pattern.kind { + match match_pair.pattern.kind { PatKind::Variant { adt_def, substs: _, variant_index: _, subpatterns: _ } => Test { span: match_pair.pattern.span, kind: TestKind::Switch { @@ -92,7 +92,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { return false; }; - match *match_pair.pattern.kind { + match match_pair.pattern.kind { PatKind::Constant { value } => { options .entry(value) @@ -130,7 +130,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { return false; }; - match *match_pair.pattern.kind { + match match_pair.pattern.kind { PatKind::Variant { adt_def: _, variant_index, .. } => { // We have a pattern testing for variant `variant_index` // set the corresponding index to true @@ -506,7 +506,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let (match_pair_index, match_pair) = candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?; - match (&test.kind, &*match_pair.pattern.kind) { + match (&test.kind, &match_pair.pattern.kind) { // If we are performing a variant switch, then this // informs variant patterns, but nothing else. ( @@ -569,7 +569,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_pair_index, candidate, prefix, - slice.as_ref(), + slice, suffix, ); Some(0) @@ -607,7 +607,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_pair_index, candidate, prefix, - slice.as_ref(), + slice, suffix, ); Some(0) @@ -678,7 +678,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // However, at this point we can still encounter or-patterns that were extracted // from previous calls to `sort_candidate`, so we need to manually address that // case to avoid panicking in `self.test()`. - if let PatKind::Or { .. } = &*match_pair.pattern.kind { + if let PatKind::Or { .. } = &match_pair.pattern.kind { return None; } @@ -708,9 +708,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, match_pair_index: usize, candidate: &mut Candidate<'pat, 'tcx>, - prefix: &'pat [Pat<'tcx>], - opt_slice: Option<&'pat Pat<'tcx>>, - suffix: &'pat [Pat<'tcx>], + prefix: &'pat [Box>], + opt_slice: &'pat Option>>, + suffix: &'pat [Box>], ) { let removed_place = candidate.match_pairs.remove(match_pair_index).place; self.prefix_slice_suffix( diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 9a1e98d3bb18d..06f24040f7be0 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -26,9 +26,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>, place: &PlaceBuilder<'tcx>, - prefix: &'pat [Pat<'tcx>], - opt_slice: Option<&'pat Pat<'tcx>>, - suffix: &'pat [Pat<'tcx>], + prefix: &'pat [Box>], + opt_slice: &'pat Option>>, + suffix: &'pat [Box>], ) { let tcx = self.tcx; let (min_length, exact_size) = if let Ok(place_resolved) = diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 684b228e87fa9..17767f4218c04 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1015,7 +1015,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let original_source_scope = self.source_scope; let span = pattern.span; self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span); - match *pattern.kind { + match pattern.kind { // Don't introduce extra copies for simple bindings PatKind::Binding { mutability, @@ -1052,7 +1052,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Some((Some(&place), span)), ); let place_builder = PlaceBuilder::from(local); - unpack!(block = self.place_into_pattern(block, pattern, place_builder, false)); + unpack!(block = self.place_into_pattern(block, *pattern, place_builder, false)); } } self.source_scope = original_source_scope; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index bf5a2e7c73fab..495738ebe1c7a 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &Pat<'tcx>) { if self.in_union_destructure { - match *pat.kind { + match pat.kind { // binding to a variable allows getting stuff out of variable PatKind::Binding { .. } // match is conditional on having this value @@ -236,7 +236,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } }; - match &*pat.kind { + match &pat.kind { PatKind::Leaf { .. } => { if let ty::Adt(adt_def, ..) = pat.ty.kind() { if adt_def.is_union() { diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 54c4b9eda70dc..c4e238c7821ea 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -91,17 +91,17 @@ impl<'tcx> Cx<'tcx> { span: ty.span, inferred_ty: self.typeck_results.node_type(ty.hir_id), }; - pattern = Pat { + pattern = Box::new(Pat { ty: pattern.ty, span: pattern.span, - kind: Box::new(PatKind::AscribeUserType { + kind: PatKind::AscribeUserType { ascription: Ascription { annotation, variance: ty::Variance::Covariant, }, subpattern: pattern, - }), - }; + }, + }); } } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index b84a84976c7d9..ae53df1f9b9a4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -78,7 +78,7 @@ impl<'tcx> Cx<'tcx> { } #[instrument(level = "debug", skip(self))] - pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> { + pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box> { let p = match self.tcx.hir().get(p.hir_id) { Node::Pat(p) => p, node => bug!("pattern became {:?}", node), 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 210d77c66e700..5af5ce407c6b9 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 @@ -26,7 +26,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { id: hir::HirId, span: Span, mir_structural_match_violation: bool, - ) -> Pat<'tcx> { + ) -> Box> { self.tcx.infer_ctxt().enter(|infcx| { let mut convert = ConstToPat::new(self, id, span, infcx); convert.to_pat(cv, mir_structural_match_violation) @@ -156,7 +156,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { &mut self, cv: mir::ConstantKind<'tcx>, mir_structural_match_violation: bool, - ) -> Pat<'tcx> { + ) -> Box> { trace!(self.treat_byte_string_as_slice); // This method is just a wrapper handling a validity check; the heavy lifting is // performed by the recursive `recur` method, which is not meant to be @@ -166,10 +166,12 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // level of indirection can be eliminated let inlined_const_as_pat = - self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| Pat { - span: self.span, - ty: cv.ty(), - kind: Box::new(PatKind::Constant { value: cv }), + self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| { + Box::new(Pat { + span: self.span, + ty: cv.ty(), + kind: PatKind::Constant { value: cv }, + }) }); if self.include_lint_checks && !self.saw_const_match_error.get() { @@ -271,7 +273,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { &self, cv: mir::ConstantKind<'tcx>, mir_structural_match_violation: bool, - ) -> Result, FallbackToConstRef> { + ) -> Result>, FallbackToConstRef> { let id = self.id; let span = self.span; let tcx = self.tcx(); @@ -425,8 +427,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { let old = self.behind_reference.replace(true); let array = tcx.deref_mir_constant(self.param_env.and(cv)); let val = PatKind::Deref { - subpattern: Pat { - kind: Box::new(PatKind::Array { + subpattern: Box::new(Pat { + kind: PatKind::Array { prefix: tcx .destructure_mir_constant(param_env, array) .fields @@ -435,10 +437,10 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { .collect::>()?, slice: None, suffix: vec![], - }), + }, span, ty: *pointee_ty, - }, + }), }; self.behind_reference.set(old); val @@ -451,8 +453,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { let old = self.behind_reference.replace(true); let array = tcx.deref_mir_constant(self.param_env.and(cv)); let val = PatKind::Deref { - subpattern: Pat { - kind: Box::new(PatKind::Slice { + subpattern: Box::new(Pat { + kind: PatKind::Slice { prefix: tcx .destructure_mir_constant(param_env, array) .fields @@ -461,10 +463,10 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { .collect::>()?, slice: None, suffix: vec![], - }), + }, span, ty: tcx.mk_slice(elem_ty), - }, + }), }; self.behind_reference.set(old); val @@ -598,6 +600,6 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { ); } - Ok(Pat { span, ty: cv.ty(), kind: Box::new(kind) }) + Ok(Box::new(Pat { span, ty: cv.ty(), kind })) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 8d6f8efb6003f..fdd74d5221dd6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -71,9 +71,9 @@ use std::ops::RangeInclusive; /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) { - if let PatKind::Or { pats } = pat.kind.as_ref() { + if let PatKind::Or { pats } = &pat.kind { for pat in pats { - expand(pat, vec); + expand(&pat, vec); } } else { vec.push(pat) @@ -255,7 +255,7 @@ impl IntRange { PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included }) }; - Pat { ty, span: DUMMY_SP, kind: Box::new(kind) } + Pat { ty, span: DUMMY_SP, kind } } /// Lint on likely incorrect range patterns (#63987) @@ -1297,7 +1297,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { let mkpat = |pat| DeconstructedPat::from_pat(cx, pat); let ctor; let fields; - match pat.kind.as_ref() { + match &pat.kind { PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { @@ -1342,9 +1342,9 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { fields = Fields::singleton(cx, pat); } ty::Adt(adt, _) => { - ctor = match pat.kind.as_ref() { + ctor = match pat.kind { PatKind::Leaf { .. } => Single, - PatKind::Variant { variant_index, .. } => Variant(*variant_index), + PatKind::Variant { variant_index, .. } => Variant(variant_index), _ => bug!(), }; let variant = &adt.variant(ctor.variant_index_for_adt(*adt)); @@ -1429,7 +1429,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { FixedLen(prefix.len() + suffix.len()) }; ctor = Slice(Slice::new(array_len, kind)); - fields = Fields::from_iter(cx, prefix.iter().chain(suffix).map(mkpat)); + fields = Fields::from_iter(cx, prefix.iter().chain(suffix).map(|p| mkpat(&*p))); } PatKind::Or { .. } => { ctor = Or; @@ -1442,15 +1442,15 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> { let is_wildcard = |pat: &Pat<'_>| { - matches!(*pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild) + matches!(pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild) }; - let mut subpatterns = self.iter_fields().map(|p| p.to_pat(cx)); - let pat = match &self.ctor { + let mut subpatterns = self.iter_fields().map(|p| Box::new(p.to_pat(cx))); + let kind = match &self.ctor { Single | Variant(_) => match self.ty.kind() { ty::Tuple(..) => PatKind::Leaf { subpatterns: subpatterns .enumerate() - .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p }) + .map(|(i, pattern)| FieldPat { field: Field::new(i), pattern }) .collect(), }, ty::Adt(adt_def, _) if adt_def.is_box() => { @@ -1506,7 +1506,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { } let suffix: Vec<_> = subpatterns.collect(); let wild = Pat::wildcard_from_ty(self.ty); - PatKind::Slice { prefix, slice: Some(wild), suffix } + PatKind::Slice { prefix, slice: Some(Box::new(wild)), suffix } } } } @@ -1523,7 +1523,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { } }; - Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(pat) } + Pat { ty: self.ty, span: DUMMY_SP, kind } } pub(super) fn is_or_pat(&self) -> bool { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index a13748a2d474a..c10fc607d1076 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -49,7 +49,7 @@ pub(crate) fn pat_from_hir<'a, 'tcx>( param_env: ty::ParamEnv<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, -) -> Pat<'tcx> { +) -> Box> { let mut pcx = PatCtxt::new(tcx, param_env, typeck_results); let result = pcx.lower_pattern(pat); if !pcx.errors.is_empty() { @@ -74,7 +74,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self } - pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> { + pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { // 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: // @@ -97,13 +97,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let unadjusted_pat = self.lower_pattern_unadjusted(pat); self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold( unadjusted_pat, - |pat, ref_ty| { + |pat: Box<_>, ref_ty| { debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty); - Pat { + Box::new(Pat { span: pat.span, ty: *ref_ty, - kind: Box::new(PatKind::Deref { subpattern: pat }), - } + kind: PatKind::Deref { subpattern: pat }, + }) }, ) } @@ -113,7 +113,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> (PatKind<'tcx>, Option>) { match self.lower_lit(expr) { - PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => { + PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { (kind, Some(ascription)) } kind => (kind, None), @@ -196,7 +196,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } - fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> { + fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { let mut ty = self.typeck_results.node_type(pat.hir_id); let kind = match pat.kind { @@ -228,7 +228,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // constants somewhere. Have them on the range pattern. for end in &[lo, hi] { if let Some((_, Some(ascription))) = end { - let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) }; + let subpattern = Box::new(Pat { span: pat.span, ty, kind }); kind = PatKind::AscribeUserType { ascription: ascription.clone(), subpattern }; } @@ -322,7 +322,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) }, }; - Pat { span: pat.span, ty, kind: Box::new(kind) } + Box::new(Pat { span: pat.span, ty, kind }) } fn lower_tuple_subpats( @@ -340,11 +340,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .collect() } - fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec> { + fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec>> { pats.iter().map(|p| self.lower_pattern(p)).collect() } - fn lower_opt_pattern(&mut self, pat: &'tcx Option<&'tcx hir::Pat<'tcx>>) -> Option> { + fn lower_opt_pattern( + &mut self, + pat: &'tcx Option<&'tcx hir::Pat<'tcx>>, + ) -> Option>> { pat.as_ref().map(|p| self.lower_pattern(p)) } @@ -441,7 +444,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { inferred_ty: self.typeck_results.node_type(hir_id), }; kind = PatKind::AscribeUserType { - subpattern: Pat { span, ty, kind: Box::new(kind) }, + subpattern: Box::new(Pat { span, ty, kind }), ascription: Ascription { annotation, variance: ty::Variance::Covariant }, }; } @@ -453,11 +456,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) -> Pat<'tcx> { + fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Box> { let ty = self.typeck_results.node_type(id); let res = self.typeck_results.qpath_res(qpath, id); - let pat_from_kind = |kind| Pat { span, ty, kind: Box::new(kind) }; + let pat_from_kind = |kind| Box::new(Pat { span, ty, kind }); let (def_id, is_associated_const) = match res { Res::Def(DefKind::Const, def_id) => (def_id, false), @@ -509,9 +512,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { span, inferred_ty: self.typeck_results().node_type(id), }; - Pat { + Box::new(Pat { span, - kind: Box::new(PatKind::AscribeUserType { + kind: PatKind::AscribeUserType { subpattern: pattern, ascription: Ascription { annotation, @@ -519,9 +522,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// `variance` field documentation for details. variance: ty::Variance::Contravariant, }, - }), + }, ty: const_.ty(), - } + }) } else { pattern } @@ -569,7 +572,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => bug!("Expected either ConstKind::Param or ConstKind::Unevaluated"), } } - mir::ConstantKind::Val(_, _) => *self.const_to_pat(value, id, span, false).kind, + mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind, } } @@ -580,7 +583,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> { let (lit, neg) = match expr.kind { hir::ExprKind::Path(ref qpath) => { - return *self.lower_path(qpath, expr.hir_id, expr.span).kind; + return self.lower_path(qpath, expr.hir_id, expr.span).kind; } hir::ExprKind::ConstBlock(ref anon_const) => { return self.lower_inline_const(anon_const, expr.hir_id, expr.span); @@ -598,7 +601,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) { - Ok(constant) => *self.const_to_pat(constant, expr.hir_id, lit.span, false).kind, + Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind, Err(LitToConstError::Reported) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 16c4d429129a9..6cbccb4bf291e 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -155,7 +155,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { return true; } - match pat.kind.as_ref() { + match pat.kind { thir::PatKind::Constant { value } => value.has_param_types_or_consts(), thir::PatKind::Range(thir::PatRange { lo, hi, .. }) => { lo.has_param_types_or_consts() || hi.has_param_types_or_consts() From bd1e6836a07fa7b96b41effc3ec90e60aaa494df Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 25 Aug 2022 14:05:01 +1000 Subject: [PATCH 2/5] Avoid some clones. `Builder::expr_into_pattern` has a single call site. Currently the `pattern` argument at the call site is always cloned. This commit changes things so that we instead do a clone within `expr_into_pattern`, but only if the pattern has the `PatKind::AscribeUserType` kind, and we only clone the annotation within the pattern instead of the entire pattern. --- compiler/rustc_mir_build/src/build/block.rs | 2 +- compiler/rustc_mir_build/src/build/matches/mod.rs | 8 ++++---- compiler/rustc_mir_build/src/build/mod.rs | 5 ++++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index ef976d6308b50..c8d4a1bf2c9e7 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -160,7 +160,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ArmHasGuard(false), Some((None, initializer_span)), ); - this.expr_into_pattern(block, (**pattern).clone(), init) // irrefutable pattern + this.expr_into_pattern(block, pattern, init) // irrefutable pattern } }) }, diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 72f8034bbc176..b4440f2dda80e 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -490,7 +490,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(super) fn expr_into_pattern( &mut self, mut block: BasicBlock, - irrefutable_pat: Pat<'tcx>, + irrefutable_pat: &Pat<'tcx>, initializer: &Expr<'tcx>, ) -> BlockAnd<()> { match irrefutable_pat.kind { @@ -525,7 +525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, .. }, - ascription: thir::Ascription { annotation, variance: _ }, + ascription: thir::Ascription { ref annotation, variance: _ }, } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); @@ -538,7 +538,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ty_source_info = self.source_info(annotation.span); - let base = self.canonical_user_type_annotations.push(annotation); + let base = self.canonical_user_type_annotations.push(annotation.clone()); self.cfg.push( block, Statement { @@ -578,7 +578,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn place_into_pattern( &mut self, block: BasicBlock, - irrefutable_pat: Pat<'tcx>, + irrefutable_pat: &Pat<'tcx>, initializer: PlaceBuilder<'tcx>, set_match_place: bool, ) -> BlockAnd<()> { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 17767f4218c04..763038c52d7fa 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1052,7 +1052,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Some((Some(&place), span)), ); let place_builder = PlaceBuilder::from(local); - unpack!(block = self.place_into_pattern(block, *pattern, place_builder, false)); + unpack!( + block = + self.place_into_pattern(block, pattern.as_ref(), place_builder, false) + ); } } self.source_scope = original_source_scope; From 2c4c8eb1a3add142c2380aecdd46ec32e42a9900 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 26 Aug 2022 11:36:24 +1000 Subject: [PATCH 3/5] Box `PatKind::Range`. Because it's the biggest variant. Also, make `PatRange` non-`Copy`, because it's 104 bytes, which is pretty big. --- compiler/rustc_middle/src/thir.rs | 10 ++++---- .../rustc_mir_build/src/build/matches/mod.rs | 2 +- .../src/build/matches/simplify.rs | 2 +- .../rustc_mir_build/src/build/matches/test.rs | 24 +++++++++---------- .../src/thir/pattern/deconstruct_pat.rs | 10 +++++--- .../rustc_mir_build/src/thir/pattern/mod.rs | 10 +++++--- compiler/rustc_ty_utils/src/consts.rs | 2 +- 7 files changed, 34 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 99d72f70ba68a..7eaf9c0099cd5 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -628,7 +628,7 @@ pub enum PatKind<'tcx> { value: mir::ConstantKind<'tcx>, }, - Range(PatRange<'tcx>), + Range(Box>), /// Matches against a slice, checking the length and extracting elements. /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. @@ -653,7 +653,7 @@ pub enum PatKind<'tcx> { }, } -#[derive(Copy, Clone, Debug, PartialEq, HashStable)] +#[derive(Clone, Debug, PartialEq, HashStable)] pub struct PatRange<'tcx> { pub lo: mir::ConstantKind<'tcx>, pub hi: mir::ConstantKind<'tcx>, @@ -767,7 +767,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { write!(f, "{}", subpattern) } PatKind::Constant { value } => write!(f, "{}", value), - PatKind::Range(PatRange { lo, hi, end }) => { + PatKind::Range(box PatRange { lo, hi, end }) => { write!(f, "{}", lo)?; write!(f, "{}", end)?; write!(f, "{}", hi) @@ -809,8 +809,8 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); - static_assert_size!(Pat<'_>, 128); - static_assert_size!(PatKind<'_>, 112); + static_assert_size!(Pat<'_>, 112); + static_assert_size!(PatKind<'_>, 96); static_assert_size!(Stmt<'_>, 56); static_assert_size!(StmtKind<'_>, 48); } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index b4440f2dda80e..bf56c26074cdb 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -979,7 +979,7 @@ enum TestKind<'tcx> { }, /// Test whether the value falls within an inclusive or exclusive range - Range(PatRange<'tcx>), + Range(Box>), /// Test that the length of the slice is equal to `len`. Len { len: u64, op: BinOp }, diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index b9954be377b36..55ed09da64fb8 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Err(match_pair) } - PatKind::Range(PatRange { lo, hi, end }) => { + PatKind::Range(box PatRange { lo, hi, end }) => { let (range, bias) = match *lo.ty().kind() { ty::Char => { (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0) diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index ce85f240603a8..19c303e0bab74 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -58,10 +58,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { kind: TestKind::Eq { value, ty: match_pair.pattern.ty }, }, - PatKind::Range(range) => { + PatKind::Range(ref range) => { assert_eq!(range.lo.ty(), match_pair.pattern.ty); assert_eq!(range.hi.ty(), match_pair.pattern.ty); - Test { span: match_pair.pattern.span, kind: TestKind::Range(range) } + Test { span: match_pair.pattern.span, kind: TestKind::Range(range.clone()) } } PatKind::Slice { ref prefix, ref slice, ref suffix } => { @@ -102,9 +102,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Variant { .. } => { panic!("you should have called add_variants_to_switch instead!"); } - PatKind::Range(range) => { + PatKind::Range(ref range) => { // Check that none of the switch values are in the range. - self.values_not_contained_in_range(range, options).unwrap_or(false) + self.values_not_contained_in_range(&*range, options).unwrap_or(false) } PatKind::Slice { .. } | PatKind::Array { .. } @@ -272,7 +272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - TestKind::Range(PatRange { lo, hi, ref end }) => { + TestKind::Range(box PatRange { lo, hi, ref end }) => { let lower_bound_success = self.cfg.start_new_block(); let target_blocks = make_target_blocks(self); @@ -540,9 +540,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Some(index) } - (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(range)) => { + (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(ref range)) => { let not_contained = - self.values_not_contained_in_range(range, options).unwrap_or(false); + self.values_not_contained_in_range(&*range, options).unwrap_or(false); if not_contained { // No switch values are contained in the pattern range, @@ -631,7 +631,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - (&TestKind::Range(test), &PatKind::Range(pat)) => { + (&TestKind::Range(ref test), &PatKind::Range(ref pat)) => { use std::cmp::Ordering::*; if test == pat { @@ -658,8 +658,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { no_overlap } - (&TestKind::Range(range), &PatKind::Constant { value }) => { - if let Some(false) = self.const_range_contains(range, value) { + (&TestKind::Range(ref range), &PatKind::Constant { value }) => { + if let Some(false) = self.const_range_contains(&*range, value) { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. Some(1) @@ -754,7 +754,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn const_range_contains( &self, - range: PatRange<'tcx>, + range: &PatRange<'tcx>, value: ConstantKind<'tcx>, ) -> Option { use std::cmp::Ordering::*; @@ -772,7 +772,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn values_not_contained_in_range( &self, - range: PatRange<'tcx>, + range: &PatRange<'tcx>, options: &FxIndexMap, u128>, ) -> Option { for &val in options.keys() { diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index fdd74d5221dd6..7f975d217bd37 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -252,7 +252,11 @@ impl IntRange { let kind = if lo == hi { PatKind::Constant { value: lo_const } } else { - PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included }) + PatKind::Range(Box::new(PatRange { + lo: lo_const, + hi: hi_const, + end: RangeEnd::Included, + })) }; Pat { ty, span: DUMMY_SP, kind } @@ -1402,7 +1406,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { } } } - &PatKind::Range(PatRange { lo, hi, end }) => { + &PatKind::Range(box PatRange { lo, hi, end }) => { let ty = lo.ty(); ctor = if let Some(int_range) = IntRange::from_range( cx.tcx, @@ -1511,7 +1515,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { } } &Str(value) => PatKind::Constant { value }, - &FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }), + &FloatRange(lo, hi, end) => PatKind::Range(Box::new(PatRange { lo, hi, end })), IntRange(range) => return range.to_pat(cx.tcx, self.ty), Wildcard | NonExhaustive => PatKind::Wild, Missing { .. } => bug!( diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index c10fc607d1076..b02b6b6f5ca62 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -134,7 +134,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match (end, cmp) { // `x..y` where `x < y`. // Non-empty because the range includes at least `x`. - (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }), + (RangeEnd::Excluded, Some(Ordering::Less)) => { + PatKind::Range(Box::new(PatRange { lo, hi, end })) + } // `x..y` where `x >= y`. The range is empty => error. (RangeEnd::Excluded, _) => { struct_span_err!( @@ -149,7 +151,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // `x..=y` where `x == y`. (RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo }, // `x..=y` where `x < y`. - (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }), + (RangeEnd::Included, Some(Ordering::Less)) => { + PatKind::Range(Box::new(PatRange { lo, hi, end })) + } // `x..=y` where `x > y` hence the range is empty => error. (RangeEnd::Included, _) => { let mut err = struct_span_err!( @@ -735,7 +739,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { PatKind::Deref { subpattern: subpattern.fold_with(folder) } } PatKind::Constant { value } => PatKind::Constant { value }, - PatKind::Range(range) => PatKind::Range(range), + PatKind::Range(ref range) => PatKind::Range(range.clone()), PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice { prefix: prefix.fold_with(folder), slice: slice.fold_with(folder), diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 6cbccb4bf291e..bb6b3e1ff5d74 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -157,7 +157,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { match pat.kind { thir::PatKind::Constant { value } => value.has_param_types_or_consts(), - thir::PatKind::Range(thir::PatRange { lo, hi, .. }) => { + thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => { lo.has_param_types_or_consts() || hi.has_param_types_or_consts() } _ => false, From a40124e01c4b10629c78b417a1fe524d929bcbe9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 26 Aug 2022 11:53:54 +1000 Subject: [PATCH 4/5] Box `CanonicalUserTypeAnnotation::CanonicalUserType`. This shrinks `Ascription`, which shrinks `PatKind::AscribeUserType`, which shrinks `Pat`. --- compiler/rustc_middle/src/thir.rs | 4 ++-- compiler/rustc_middle/src/ty/context.rs | 2 +- .../rustc_mir_build/src/build/expr/as_constant.rs | 12 ++++++------ compiler/rustc_mir_build/src/build/expr/as_place.rs | 8 ++++---- compiler/rustc_mir_build/src/build/expr/into.rs | 4 ++-- compiler/rustc_mir_build/src/thir/cx/block.rs | 2 +- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 7eaf9c0099cd5..120fa787009da 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -809,8 +809,8 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); - static_assert_size!(Pat<'_>, 112); - static_assert_size!(PatKind<'_>, 96); + static_assert_size!(Pat<'_>, 80); + static_assert_size!(PatKind<'_>, 64); static_assert_size!(Stmt<'_>, 56); static_assert_size!(StmtKind<'_>, 48); } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 052bb1263c98f..cd3201e77ce9c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -874,7 +874,7 @@ pub type CanonicalUserTypeAnnotations<'tcx> = #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct CanonicalUserTypeAnnotation<'tcx> { - pub user_ty: CanonicalUserType<'tcx>, + pub user_ty: Box>, pub span: Span, pub inferred_ty: Ty<'tcx>, } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index b316a6eeac1ca..3549b47478cbd 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -42,10 +42,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span, user_ty: None, literal } } ExprKind::NonHirLiteral { lit, ref user_ty } => { - let user_ty = user_ty.as_ref().map(|box user_ty| { + let user_ty = user_ty.as_ref().map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span, - user_ty: *user_ty, + user_ty: user_ty.clone(), inferred_ty: ty, }) }); @@ -54,10 +54,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span, user_ty: user_ty, literal } } ExprKind::ZstLiteral { ref user_ty } => { - let user_ty = user_ty.as_ref().map(|box user_ty| { + let user_ty = user_ty.as_ref().map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span, - user_ty: *user_ty, + user_ty: user_ty.clone(), inferred_ty: ty, }) }); @@ -66,10 +66,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span, user_ty: user_ty, literal } } ExprKind::NamedConst { def_id, substs, ref user_ty } => { - let user_ty = user_ty.as_ref().map(|box user_ty| { + let user_ty = user_ty.as_ref().map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span, - user_ty: *user_ty, + user_ty: user_ty.clone(), inferred_ty: ty, }) }); diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index b8277f28cdc43..46dbd8a136b52 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -522,11 +522,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrow_temps, ) ); - if let Some(box user_ty) = user_ty { + if let Some(user_ty) = user_ty { let annotation_index = this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span: source_info.span, - user_ty: *user_ty, + user_ty: user_ty.clone(), inferred_ty: expr.ty, }); @@ -551,11 +551,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source = &this.thir[source]; let temp = unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability)); - if let Some(box user_ty) = user_ty { + if let Some(user_ty) = user_ty { let annotation_index = this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span: source_info.span, - user_ty: *user_ty, + user_ty: user_ty.clone(), inferred_ty: expr.ty, }); this.cfg.push( diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 48ec7a06724a1..74509646c17c6 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -378,10 +378,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; let inferred_ty = expr.ty; - let user_ty = user_ty.as_ref().map(|box user_ty| { + let user_ty = user_ty.as_ref().map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span: source_info.span, - user_ty: *user_ty, + user_ty: user_ty.clone(), inferred_ty, }) }); diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index c4e238c7821ea..321353ca20bae 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -87,7 +87,7 @@ impl<'tcx> Cx<'tcx> { { debug!("mirror_stmts: user_ty={:?}", user_ty); let annotation = CanonicalUserTypeAnnotation { - user_ty, + user_ty: Box::new(user_ty), span: ty.span, inferred_ty: self.typeck_results.node_type(ty.hir_id), }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index b02b6b6f5ca62..21a2cb32aa76e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -443,7 +443,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) { debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span); let annotation = CanonicalUserTypeAnnotation { - user_ty, + user_ty: Box::new(user_ty), span, inferred_ty: self.typeck_results.node_type(hir_id), }; @@ -512,7 +512,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let user_provided_types = self.typeck_results().user_provided_types(); if let Some(&user_ty) = user_provided_types.get(id) { let annotation = CanonicalUserTypeAnnotation { - user_ty, + user_ty: Box::new(user_ty), span, inferred_ty: self.typeck_results().node_type(id), }; From 43a0268f3a28fa53ad8290720002984cff785224 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 26 Aug 2022 12:06:13 +1000 Subject: [PATCH 5/5] Use boxed slices in `PatKind`. To shrink it a little more. --- compiler/rustc_middle/src/thir.rs | 20 +++++++++---------- compiler/rustc_middle/src/thir/visit.rs | 6 +++--- .../rustc_mir_build/src/build/matches/mod.rs | 6 +++--- .../src/thir/pattern/const_to_pat.rs | 6 +++--- .../src/thir/pattern/deconstruct_pat.rs | 15 +++++++++----- .../rustc_mir_build/src/thir/pattern/mod.rs | 8 +++++++- 6 files changed, 36 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 120fa787009da..59e14337f4ed8 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -634,22 +634,22 @@ pub enum PatKind<'tcx> { /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. /// e.g., `&[ref xs @ ..]`. Slice { - prefix: Vec>>, + prefix: Box<[Box>]>, slice: Option>>, - suffix: Vec>>, + suffix: Box<[Box>]>, }, /// Fixed match against an array; irrefutable. Array { - prefix: Vec>>, + prefix: Box<[Box>]>, slice: Option>>, - suffix: Vec>>, + suffix: Box<[Box>]>, }, /// An or-pattern, e.g. `p | q`. /// Invariant: `pats.len() >= 2`. Or { - pats: Vec>>, + pats: Box<[Box>]>, }, } @@ -775,7 +775,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { PatKind::Slice { ref prefix, ref slice, ref suffix } | PatKind::Array { ref prefix, ref slice, ref suffix } => { write!(f, "[")?; - for p in prefix { + for p in prefix.iter() { write!(f, "{}{}", start_or_comma(), p)?; } if let Some(ref slice) = *slice { @@ -786,13 +786,13 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } write!(f, "..")?; } - for p in suffix { + for p in suffix.iter() { write!(f, "{}{}", start_or_comma(), p)?; } write!(f, "]") } PatKind::Or { ref pats } => { - for pat in pats { + for pat in pats.iter() { write!(f, "{}{}", start_or_continue(" | "), pat)?; } Ok(()) @@ -809,8 +809,8 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); - static_assert_size!(Pat<'_>, 80); - static_assert_size!(PatKind<'_>, 64); + static_assert_size!(Pat<'_>, 72); + static_assert_size!(PatKind<'_>, 56); static_assert_size!(Stmt<'_>, 56); static_assert_size!(StmtKind<'_>, 48); } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 5168c2120f43d..79a0e75aa7c78 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -232,18 +232,18 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' Constant { value: _ } => {} Range(_) => {} Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { - for subpattern in prefix { + for subpattern in prefix.iter() { visitor.visit_pat(&subpattern); } if let Some(pat) = slice { visitor.visit_pat(&pat); } - for subpattern in suffix { + for subpattern in suffix.iter() { visitor.visit_pat(&subpattern); } } Or { pats } => { - for pat in pats { + for pat in pats.iter() { visitor.visit_pat(&pat); } } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index bf56c26074cdb..a316c2e7d6e18 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -764,7 +764,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | PatKind::Slice { ref prefix, ref slice, ref suffix } => { let from = u64::try_from(prefix.len()).unwrap(); let to = u64::try_from(suffix.len()).unwrap(); - for subpattern in prefix { + for subpattern in prefix.iter() { self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); } for subpattern in slice { @@ -774,7 +774,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { f, ); } - for subpattern in suffix { + for subpattern in suffix.iter() { self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); } } @@ -827,7 +827,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // may not all be in the leftmost subpattern. For example in // `let (x | y) = ...`, the primary binding of `y` occurs in // the right subpattern - for subpattern in pats { + for subpattern in pats.iter() { self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f); } } 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 5af5ce407c6b9..b58685e895809 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 @@ -400,7 +400,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { .map(|val| self.recur(*val, false)) .collect::>()?, slice: None, - suffix: Vec::new(), + suffix: Box::new([]), }, ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() { // These are not allowed and will error elsewhere anyway. @@ -436,7 +436,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { .map(|val| self.recur(*val, false)) .collect::>()?, slice: None, - suffix: vec![], + suffix: Box::new([]), }, span, ty: *pointee_ty, @@ -462,7 +462,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { .map(|val| self.recur(*val, false)) .collect::>()?, slice: None, - suffix: vec![], + suffix: Box::new([]), }, span, ty: tcx.mk_slice(elem_ty), diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 7f975d217bd37..5105f059f9b64 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -72,7 +72,7 @@ use std::ops::RangeInclusive; fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) { if let PatKind::Or { pats } = &pat.kind { - for pat in pats { + for pat in pats.iter() { expand(&pat, vec); } } else { @@ -1433,7 +1433,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { FixedLen(prefix.len() + suffix.len()) }; ctor = Slice(Slice::new(array_len, kind)); - fields = Fields::from_iter(cx, prefix.iter().chain(suffix).map(|p| mkpat(&*p))); + fields = + Fields::from_iter(cx, prefix.iter().chain(suffix.iter()).map(|p| mkpat(&*p))); } PatKind::Or { .. } => { ctor = Or; @@ -1489,7 +1490,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { FixedLen(_) => PatKind::Slice { prefix: subpatterns.collect(), slice: None, - suffix: vec![], + suffix: Box::new([]), }, VarLen(prefix, _) => { let mut subpatterns = subpatterns.peekable(); @@ -1508,9 +1509,13 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { subpatterns.next(); } } - let suffix: Vec<_> = subpatterns.collect(); + let suffix: Box<[_]> = subpatterns.collect(); let wild = Pat::wildcard_from_ty(self.ty); - PatKind::Slice { prefix, slice: Some(Box::new(wild)), suffix } + PatKind::Slice { + prefix: prefix.into_boxed_slice(), + slice: Some(Box::new(wild)), + suffix, + } } } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 21a2cb32aa76e..d2f93b679acc5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -344,7 +344,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .collect() } - fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec>> { + fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box>]> { pats.iter().map(|p| self.lower_pattern(p)).collect() } @@ -653,6 +653,12 @@ impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Vec { } } +impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<[T]> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + self.iter().map(|t| t.fold_with(folder)).collect() + } +} + impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option { fn super_fold_with>(&self, folder: &mut F) -> Self { self.as_ref().map(|t| t.fold_with(folder))