diff options
| author | bors <bors@rust-lang.org> | 2023-02-16 16:11:54 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-02-16 16:11:54 +0000 |
| commit | c5d1b3ea9665e77e3af2f17b311bf65469eedc19 (patch) | |
| tree | 86493d29ad1fbfdf42869d9c848c8b4336f42360 /compiler/rustc_middle | |
| parent | af3c8b27266e290cf65704284f6862d0f90ee4fc (diff) | |
| parent | 9a53cee8681348a7ba46158a4e80d36b1b9789d8 (diff) | |
| download | rust-c5d1b3ea9665e77e3af2f17b311bf65469eedc19.tar.gz rust-c5d1b3ea9665e77e3af2f17b311bf65469eedc19.zip | |
Auto merge of #108020 - nnethercote:opt-mk_region, r=compiler-errors
Optimize `mk_region` PR #107869 avoiding some interning under `mk_ty` by special-casing `Ty` variants with simple (integer) bodies. This PR does something similar for regions. r? `@compiler-errors`
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/infer/canonical.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 126 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/fold.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/generics.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/opaque_types.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/print/pretty.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/util.rs | 6 |
8 files changed, 133 insertions, 43 deletions
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index ada516aa032..bb617e692cc 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -353,7 +353,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { var: ty::BoundVar::from_usize(i), kind: ty::BrAnon(i as u32, None), }; - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() + tcx.mk_re_late_bound(ty::INNERMOST, br).into() } CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4aef071cd98..b47996ffba2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -243,11 +243,20 @@ impl<'tcx> CtxtInterners<'tcx> { } } +// For these preinterned values, an alternative would be to have +// variable-length vectors that grow as needed. But that turned out to be +// slightly more complex and no faster. + const NUM_PREINTERNED_TY_VARS: u32 = 100; const NUM_PREINTERNED_FRESH_TYS: u32 = 20; const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3; const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3; +// This number may seem high, but it is reached in all but the smallest crates. +const NUM_PREINTERNED_RE_VARS: u32 = 500; +const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2; +const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20; + pub struct CommonTypes<'tcx> { pub unit: Ty<'tcx>, pub bool: Ty<'tcx>, @@ -295,6 +304,14 @@ pub struct CommonLifetimes<'tcx> { /// Erased region, used outside of type inference. pub re_erased: Region<'tcx>, + + /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`. + pub re_vars: Vec<Region<'tcx>>, + + /// Pre-interned values of the form: + /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) }) + /// for small values of `i` and `v`. + pub re_late_bounds: Vec<Vec<Region<'tcx>>>, } pub struct CommonConsts<'tcx> { @@ -358,7 +375,31 @@ impl<'tcx> CommonLifetimes<'tcx> { )) }; - CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) } + let re_vars = + (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect(); + + let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I) + .map(|i| { + (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V) + .map(|v| { + mk(ty::ReLateBound( + ty::DebruijnIndex::from(i), + ty::BoundRegion { + var: ty::BoundVar::from(v), + kind: ty::BrAnon(v, None), + }, + )) + }) + .collect() + }) + .collect(); + + CommonLifetimes { + re_static: mk(ty::ReStatic), + re_erased: mk(ty::ReErased), + re_vars, + re_late_bounds, + } } } @@ -697,15 +738,15 @@ impl<'tcx> TyCtxt<'tcx> { /// Constructs a `RegionKind::ReError` lifetime. #[track_caller] - pub fn re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> { - self.mk_region(ty::ReError(reported)) + pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> { + self.intern_region(ty::ReError(reported)) } /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it /// gets used. #[track_caller] - pub fn re_error_misc(self) -> Region<'tcx> { - self.re_error_with_message( + pub fn mk_re_error_misc(self) -> Region<'tcx> { + self.mk_re_error_with_message( DUMMY_SP, "RegionKind::ReError constructed but no error reported", ) @@ -714,9 +755,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given /// `msg` to ensure it gets used. #[track_caller] - pub fn re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> { + pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> { let reported = self.sess.delay_span_bug(span, msg); - self.re_error(reported) + self.mk_re_error(reported) } /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed` @@ -1517,7 +1558,7 @@ macro_rules! direct_interners { } direct_interners! { - region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>, + region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>, const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>, const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: intern_layout(LayoutS): Layout -> Layout<'tcx>, @@ -1631,13 +1672,6 @@ impl<'tcx> TyCtxt<'tcx> { }) } - /// Same a `self.mk_region(kind)`, but avoids accessing the interners if - /// `*r == kind`. - #[inline] - pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { - if *r == kind { r } else { self.mk_region(kind) } - } - // Avoid this in favour of more specific `mk_*` methods, where possible. #[allow(rustc::usage_of_ty_tykind)] #[inline] @@ -1966,7 +2000,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { match param.kind { GenericParamDefKind::Lifetime => { - self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into() + self.mk_re_early_bound(param.to_early_bound_region_data()).into() } GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), GenericParamDefKind::Const { .. } => self @@ -1998,6 +2032,66 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs)) } + #[inline] + pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> { + self.intern_region(ty::ReEarlyBound(early_bound_region)) + } + + #[inline] + pub fn mk_re_late_bound( + self, + debruijn: ty::DebruijnIndex, + bound_region: ty::BoundRegion, + ) -> Region<'tcx> { + // Use a pre-interned one when possible. + if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region + && var.as_u32() == v + && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize()) + && let Some(re) = inner.get(v as usize).copied() + { + re + } else { + self.intern_region(ty::ReLateBound(debruijn, bound_region)) + } + } + + #[inline] + pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> { + self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region })) + } + + #[inline] + pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> { + // Use a pre-interned one when possible. + self.lifetimes + .re_vars + .get(v.as_usize()) + .copied() + .unwrap_or_else(|| self.intern_region(ty::ReVar(v))) + } + + #[inline] + pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> { + self.intern_region(ty::RePlaceholder(placeholder)) + } + + // Avoid this in favour of more specific `mk_re_*` methods, where possible, + // to avoid the cost of the `match`. + pub fn mk_region(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> { + match kind { + ty::ReEarlyBound(region) => self.mk_re_early_bound(region), + ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region), + ty::ReFree(ty::FreeRegion { scope, bound_region }) => { + self.mk_re_free(scope, bound_region) + } + ty::ReStatic => self.lifetimes.re_static, + ty::ReVar(vid) => self.mk_re_var(vid), + ty::RePlaceholder(region) => self.mk_re_placeholder(region), + ty::ReErased => self.lifetimes.re_erased, + ty::ReError(reported) => self.mk_re_error(reported), + } + } + pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { self.mk_place_elem(place, PlaceElem::Field(f, ty)) } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 352daa8fc29..ee36e60bff1 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -234,7 +234,7 @@ where // debruijn index. Then we adjust it to the // correct depth. assert_eq!(debruijn1, ty::INNERMOST); - self.tcx.reuse_or_mk_region(region, ty::ReLateBound(debruijn, br)) + self.tcx.mk_re_late_bound(debruijn, br) } else { region } @@ -349,10 +349,7 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { self.replace_late_bound_regions_uncached(value, |br| { - self.mk_region(ty::ReFree(ty::FreeRegion { - scope: all_outlive_scope, - bound_region: br.kind, - })) + self.mk_re_free(all_outlive_scope, br.kind) }) } @@ -365,10 +362,10 @@ impl<'tcx> TyCtxt<'tcx> { value, FnMutDelegate { regions: &mut |r: ty::BoundRegion| { - self.mk_region(ty::ReLateBound( + self.mk_re_late_bound( ty::INNERMOST, ty::BoundRegion { var: shift_bv(r.var), kind: r.kind }, - )) + ) }, types: &mut |t: ty::BoundTy| { self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind }) @@ -409,7 +406,7 @@ impl<'tcx> TyCtxt<'tcx> { }) .expect_region(); let br = ty::BoundRegion { var, kind }; - self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) + self.tcx.mk_re_late_bound(ty::INNERMOST, br) } fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { let entry = self.map.entry(bt.var); @@ -479,8 +476,7 @@ impl<'tcx> ir::TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> { match *r { ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { let debruijn = debruijn.shifted_in(self.amount); - let shifted = ty::ReLateBound(debruijn, br); - self.tcx.mk_region(shifted) + self.tcx.mk_re_late_bound(debruijn, br) } _ => r, } @@ -521,7 +517,7 @@ pub fn shift_region<'tcx>( ) -> ty::Region<'tcx> { match *region { ty::ReLateBound(debruijn, br) if amount > 0 => { - tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br)) + tcx.mk_re_late_bound(debruijn.shifted_in(amount), br) } _ => region, } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index ea95a38f272..c29a94c9714 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -100,7 +100,7 @@ impl GenericParamDef { preceding_substs: &[ty::GenericArg<'tcx>], ) -> ty::GenericArg<'tcx> { match &self.kind { - ty::GenericParamDefKind::Lifetime => tcx.re_error_misc().into(), + ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(), ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(), ty::GenericParamDefKind::Const { .. } => { tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into() diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 66c878c8b63..8aeef4684b3 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -143,7 +143,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { ) .emit(); - self.interner().re_error(e) + self.interner().mk_re_error(e) } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f50a5d89d3d..1a228e99eff 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -182,7 +182,7 @@ impl<'tcx> RegionHighlightMode<'tcx> { /// Convenience wrapper for `highlighting_region`. pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) { - self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number) + self.highlighting_region(self.tcx.mk_re_var(vid), number) } /// Returns `Some(n)` with the number to use for the given region, if any. @@ -2271,7 +2271,7 @@ impl<'a, 'tcx> ty::ir::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { }; if let ty::ReLateBound(debruijn1, br) = *region { assert_eq!(debruijn1, ty::INNERMOST); - self.tcx.mk_region(ty::ReLateBound(self.current_index, br)) + self.tcx.mk_re_late_bound(self.current_index, br) } else { region } @@ -2383,10 +2383,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name); - return tcx.mk_region(ty::ReLateBound( + return tcx.mk_re_late_bound( ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, - )); + ); } } @@ -2398,10 +2398,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(def_id, name); - return tcx.mk_region(ty::ReLateBound( + return tcx.mk_re_late_bound( ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, - )); + ); } } @@ -2411,10 +2411,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = br.kind; - return tcx.mk_region(ty::ReLateBound( + return tcx.mk_re_late_bound( ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, - )); + ); } } @@ -2426,7 +2426,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { start_or_continue(&mut self, "for<", ", "); do_continue(&mut self, name); } - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })) + tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }) }; let mut folder = RegionFolder { tcx, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c613b3627f2..85c63131bff 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1187,7 +1187,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> { if index == self.index { Err(()) } else { - Ok(self.interner().mk_region(ty::ReLateBound(index.shifted_out(1), bv))) + Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv)) } } else { r.try_super_fold_with(self) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 35831ff8706..7f5ffe6f27a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -564,14 +564,14 @@ impl<'tcx> TyCtxt<'tcx> { self, closure_def_id: DefId, closure_substs: SubstsRef<'tcx>, - env_region: ty::RegionKind<'tcx>, + env_region: ty::Region<'tcx>, ) -> Option<Ty<'tcx>> { let closure_ty = self.mk_closure(closure_def_id, closure_substs); let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { - ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty), - ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty), + ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty), + ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; Some(env_ty) |
