Pre-intern some commonly used type variables.

This requires some rearrangement of plumbing, such as adding
`mk_fresh_{,int_,float_}ty` and removing `mk_ty_infer`.
This commit is contained in:
Nicholas Nethercote 2023-02-08 11:52:19 +11:00
parent 5b8f284536
commit 6248bbbf26
6 changed files with 80 additions and 31 deletions

View File

@ -273,12 +273,8 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
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,
},
};

View File

@ -58,14 +58,9 @@ pub fn new(infcx: &'a InferCtxt<'tcx>, keep_static: bool) -> TypeFreshener<'a, '
}
}
fn freshen_ty<F>(
&mut self,
opt_ty: Option<Ty<'tcx>>,
key: ty::InferTy,
freshener: F,
) -> Ty<'tcx>
fn freshen_ty<F>(&mut self, opt_ty: Option<Ty<'tcx>>, 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 @@ fn freshen_ty<F>(
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 @@ fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'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 @@ fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'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 @@ fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'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),
),
),

View File

@ -241,6 +241,11 @@ fn intern_predicate(
}
}
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<Ty<'tcx>>,
/// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`.
pub fresh_tys: Vec<Ty<'tcx>>,
/// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`.
pub fresh_int_tys: Vec<Ty<'tcx>>,
/// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`.
pub fresh_float_tys: Vec<Ty<'tcx>>,
}
pub struct CommonLifetimes<'tcx> {
@ -289,6 +307,15 @@ fn new(
) -> 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 @@ fn new(
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 @@ pub fn mk_generator_witness_mir(self, id: DefId, substs: SubstsRef<'tcx>) -> Ty<
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::ConstKind<'tcx>>, 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]

View File

@ -1209,7 +1209,7 @@ fn pretty_print_dyn_existential(
// 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 @@ pub struct PrintClosureAsImpl<'tcx> {
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()))
}

View File

@ -540,7 +540,7 @@ fn print_dyn_existential(
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)?;
}

View File

@ -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() {