diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index c4905a934cb..ae00042eae7 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -273,12 +273,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ct_op: |c| c, ty_op: |t| match *t.kind() { ty::Infer(ty::TyVar(_)) => self.tcx.mk_ty_var(ty::TyVid::from_u32(0)), - ty::Infer(ty::IntVar(_)) => { - self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 })) - } - ty::Infer(ty::FloatVar(_)) => { - self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 })) - } + ty::Infer(ty::IntVar(_)) => self.tcx.mk_int_var(ty::IntVid { index: 0 }), + ty::Infer(ty::FloatVar(_)) => self.tcx.mk_float_var(ty::FloatVid { index: 0 }), _ => t, }, }; diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 1c76950cc6c..073a2b0753d 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -58,14 +58,9 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { } } - fn freshen_ty( - &mut self, - opt_ty: Option>, - key: ty::InferTy, - freshener: F, - ) -> Ty<'tcx> + fn freshen_ty(&mut self, opt_ty: Option>, key: ty::InferTy, mk_fresh: F) -> Ty<'tcx> where - F: FnOnce(u32) -> ty::InferTy, + F: FnOnce(u32) -> Ty<'tcx>, { if let Some(ty) = opt_ty { return ty.fold_with(self); @@ -76,7 +71,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { Entry::Vacant(entry) => { let index = self.ty_freshen_count; self.ty_freshen_count += 1; - let t = self.infcx.tcx.mk_ty_infer(freshener(index)); + let t = mk_fresh(index); entry.insert(t); t } @@ -204,7 +199,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { match v { ty::TyVar(v) => { let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - Some(self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)) + Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| self.infcx.tcx.mk_fresh_ty(n))) } ty::IntVar(v) => Some( @@ -216,7 +211,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { .probe_value(v) .map(|v| v.to_type(self.infcx.tcx)), ty::IntVar(v), - ty::FreshIntTy, + |n| self.infcx.tcx.mk_fresh_int_ty(n), ), ), @@ -229,7 +224,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { .probe_value(v) .map(|v| v.to_type(self.infcx.tcx)), ty::FloatVar(v), - ty::FreshFloatTy, + |n| self.infcx.tcx.mk_fresh_float_ty(n), ), ), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 04537ad635a..5fe8a4521ca 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -241,6 +241,11 @@ impl<'tcx> CtxtInterners<'tcx> { } } +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; + pub struct CommonTypes<'tcx> { pub unit: Ty<'tcx>, pub bool: Ty<'tcx>, @@ -266,7 +271,20 @@ pub struct CommonTypes<'tcx> { /// Dummy type used for the `Self` of a `TraitRef` created for converting /// a trait object, and which gets removed in `ExistentialTraitRef`. /// This type must not appear anywhere in other converted types. + /// `Infer(ty::FreshTy(0))` does the job. pub trait_object_dummy_self: Ty<'tcx>, + + /// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`. + pub ty_vars: Vec>, + + /// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`. + pub fresh_tys: Vec>, + + /// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`. + pub fresh_int_tys: Vec>, + + /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`. + pub fresh_float_tys: Vec>, } pub struct CommonLifetimes<'tcx> { @@ -289,6 +307,15 @@ impl<'tcx> CommonTypes<'tcx> { ) -> CommonTypes<'tcx> { let mk = |ty| interners.intern_ty(ty, sess, untracked); + let ty_vars = + (0..NUM_PREINTERNED_TY_VARS).map(|n| mk(Infer(ty::TyVar(TyVid::from(n))))).collect(); + let fresh_tys: Vec<_> = + (0..NUM_PREINTERNED_FRESH_TYS).map(|n| mk(Infer(ty::FreshTy(n)))).collect(); + let fresh_int_tys: Vec<_> = + (0..NUM_PREINTERNED_FRESH_INT_TYS).map(|n| mk(Infer(ty::FreshIntTy(n)))).collect(); + let fresh_float_tys: Vec<_> = + (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect(); + CommonTypes { unit: mk(Tuple(List::empty())), bool: mk(Bool), @@ -311,7 +338,12 @@ impl<'tcx> CommonTypes<'tcx> { str_: mk(Str), self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })), - trait_object_dummy_self: mk(Infer(ty::FreshTy(0))), + trait_object_dummy_self: fresh_tys[0], + + ty_vars, + fresh_tys, + fresh_int_tys, + fresh_float_tys, } } } @@ -1867,29 +1899,55 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(GeneratorWitnessMIR(id, substs)) } - #[inline] - pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> { - self.mk_ty_infer(TyVar(v)) - } - #[inline] pub fn mk_const(self, kind: impl Into>, ty: Ty<'tcx>) -> Const<'tcx> { self.mk_const_internal(ty::ConstData { kind: kind.into(), ty }) } + #[inline] + pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> { + // Use a pre-interned one when possible. + self.types.ty_vars.get(v.as_usize()).copied().unwrap_or_else(|| self.mk_ty(Infer(TyVar(v)))) + } + #[inline] pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> { - self.mk_ty_infer(IntVar(v)) + self.mk_ty(Infer(IntVar(v))) } #[inline] pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> { - self.mk_ty_infer(FloatVar(v)) + self.mk_ty(Infer(FloatVar(v))) } #[inline] - pub fn mk_ty_infer(self, it: InferTy) -> Ty<'tcx> { - self.mk_ty(Infer(it)) + pub fn mk_fresh_ty(self, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + self.types + .fresh_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| self.mk_ty(Infer(ty::FreshTy(n)))) + } + + #[inline] + pub fn mk_fresh_int_ty(self, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + self.types + .fresh_int_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| self.mk_ty(Infer(ty::FreshIntTy(n)))) + } + + #[inline] + pub fn mk_fresh_float_ty(self, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + self.types + .fresh_float_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| self.mk_ty(Infer(ty::FreshFloatTy(n)))) } #[inline] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index e9a10f483e5..c4a95ddacbf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1209,7 +1209,7 @@ pub trait PrettyPrinter<'tcx>: // in order to place the projections inside the `<...>`. if !resugared { // Use a type that can't appear in defaults of type parameters. - let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0)); + let dummy_cx = cx.tcx().mk_fresh_ty(0); let principal = principal.with_self_ty(cx.tcx(), dummy_cx); let args = cx @@ -2696,7 +2696,7 @@ define_print_and_forward_display! { ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0)); + let dummy_self = cx.tcx().mk_fresh_ty(0); let trait_ref = self.with_self_ty(cx.tcx(), dummy_self); p!(print(trait_ref.print_only_trait_path())) } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 00d1ff5ceed..c58b6a24ab5 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -540,7 +540,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { match predicate.as_ref().skip_binder() { ty::ExistentialPredicate::Trait(trait_ref) => { // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0)); + let dummy_self = cx.tcx.mk_fresh_ty(0); let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self); cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?; } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 1136b70a0b9..5cfb6cf332e 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -879,7 +879,7 @@ pub fn object_region_bounds<'tcx>( // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically // a placeholder type. - let open_ty = tcx.mk_ty_infer(ty::FreshTy(0)); + let open_ty = tcx.mk_fresh_ty(0); let predicates = existential_predicates.iter().filter_map(|predicate| { if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() {