Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 82 additions & 62 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, sym};
use rustc_structures::{CrateType, Limit};
use rustc_type_ir::TyKind::*;
pub use rustc_type_ir::lift::Lift;
use rustc_type_ir::{CollectAndApply, WithCachedTypeInfo, elaborate, search_graph};
use rustc_type_ir::{
CollectAndApply, PlaceholderType, WithCachedTypeInfo, elaborate, search_graph,
};
use tracing::{debug, instrument};

use crate::arena::Arena;
Expand Down Expand Up @@ -284,28 +286,22 @@ 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.
//
// All numbers have been chosen based on profiling data.

const NUM_PREINTERNED_INFER_TY_VARS: u32 = 512;
const NUM_PREINTERNED_INFER_FRESH_TYS: u32 = 20;
const NUM_PREINTERNED_INFER_FRESH_INT_TYS: u32 = 3;
const NUM_PREINTERNED_INFER_FRESH_FLOAT_TYS: u32 = 3;
const NUM_PREINTERNED_BOUND_BOUND_ANONS_I: u32 = 3;
const NUM_PREINTERNED_BOUND_BOUND_ANONS_V: u32 = 20;
const NUM_PREINTERNED_BOUND_CANONICAL_ANONS: u32 = 128;
const NUM_PREINTERNED_PLACEHOLDER_ROOT_ANONS: u32 = 128;

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;
const NUM_PREINTERNED_ANON_BOUND_TYS_I: u32 = 3;

// From general profiling of the *max vars during canonicalization* of a value:
// - about 90% of the time, there are no canonical vars
// - about 9% of the time, there is only one canonical var
// - there are rarely more than 3-5 canonical vars (with exceptions in particularly pathological
// cases)
// This may not match the number of bound vars found in `for`s.
// Given that this is all heap interned, it seems likely that interning fewer
// vars here won't make an appreciable difference. Though, if we were to inline the data (in an
// array), we may want to consider reducing the number for canonicalized vars down to 4 or so.
const NUM_PREINTERNED_ANON_BOUND_TYS_V: u32 = 20;

// 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_ANON_RE_BOUNDS_I: u32 = 3;
const NUM_PREINTERNED_ANON_RE_BOUNDS_V: u32 = 20;
const NUM_PREINTERNED_RE_BOUND_BOUND_ANONS_I: u32 = 3;
const NUM_PREINTERNED_RE_BOUND_BOUND_ANONS_V: u32 = 20;
const NUM_PREINTERNED_RE_BOUND_CANONICAL_ANONS: u32 = 20;

pub struct CommonTypes<'tcx> {
pub unit: Ty<'tcx>,
Expand Down Expand Up @@ -360,26 +356,37 @@ pub struct CommonTypes<'tcx> {
pub trait_object_dummy_self: Ty<'tcx>,

/// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`.
pub ty_vars: Vec<Ty<'tcx>>,
pub infer_ty_vars: Vec<Ty<'tcx>>,

/// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`.
pub fresh_tys: Vec<Ty<'tcx>>,
pub infer_fresh_tys: Vec<Ty<'tcx>>,

/// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`.
pub fresh_int_tys: Vec<Ty<'tcx>>,
pub infer_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 infer_fresh_float_tys: Vec<Ty<'tcx>>,

/// Pre-interned values of the form:
/// `Bound(
/// BoundVarIndexKind::Bound(DebruijnIndex(i)),
/// BoundTy { var: v, kind: BoundTyKind::Anon }
/// )`
/// for small values of `i` and `v`.
pub bound_bound_anons: Vec<Vec<Ty<'tcx>>>,

/// Pre-interned values of the form:
/// `Bound(BoundVarIndexKind::Bound(DebruijnIndex(i)), BoundTy { var: v, kind:
/// BoundTyKind::Anon})` for small values of `i` and `v`.
pub anon_bound_tys: Vec<Vec<Ty<'tcx>>>,

// Pre-interned values of the form:
// `Bound(BoundVarIndexKind::Canonical, BoundTy { var: v, kind: BoundTyKind::Anon })`
// for small values of `v`.
pub anon_canonical_bound_tys: Vec<Ty<'tcx>>,
/// `Bound(BoundVarIndexKind::Canonical, BoundTy { var: v, kind: BoundTyKind::Anon })`
/// for small values of `v`.
pub bound_canonical_anons: Vec<Ty<'tcx>>,

/// Pre-interned values of the form:
/// `Placeholder(Placeholder {
/// universe: UniverseIndex::ROOT,
/// bound: BoundTy { var: v, kind: BoundTyKind::Anon }
/// })`
/// for small values of `v`.
pub placeholder_root_anons: Vec<Ty<'tcx>>,
}

pub struct CommonLifetimes<'tcx> {
Expand All @@ -389,18 +396,18 @@ 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`.
/// Pre-interned `ReVar(ty::RegionVid(n))` for small values of `n`.
pub re_vars: Vec<Region<'tcx>>,

/// Pre-interned values of the form:
/// `ReBound(BoundVarIndexKind::Bound(DebruijnIndex(i)), BoundRegion { var: v, kind: BoundRegionKind::Anon })`
/// for small values of `i` and `v`.
pub anon_re_bounds: Vec<Vec<Region<'tcx>>>,
pub re_bound_bound_anons: Vec<Vec<Region<'tcx>>>,

// Pre-interned values of the form:
// `ReBound(BoundVarIndexKind::Canonical, BoundRegion { var: v, kind: BoundRegionKind::Anon })`
// for small values of `v`.
pub anon_re_canonical_bounds: Vec<Region<'tcx>>,
/// Pre-interned values of the form:
/// `ReBound(BoundVarIndexKind::Canonical, BoundRegion { var: v, kind: BoundRegionKind::Anon })`
/// for small values of `v`.
pub re_bound_canonical_anons: Vec<Region<'tcx>>,
}

pub struct CommonConsts<'tcx> {
Expand All @@ -415,18 +422,21 @@ impl<'tcx> CommonTypes<'tcx> {
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
let mk = |ty| interners.intern_ty(ty);

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();
let infer_ty_vars = (0..NUM_PREINTERNED_INFER_TY_VARS)
.map(|n| mk(Infer(ty::TyVar(TyVid::from(n)))))
.collect();
let infer_fresh_tys: Vec<_> =
(0..NUM_PREINTERNED_INFER_FRESH_TYS).map(|n| mk(Infer(ty::FreshTy(n)))).collect();
let infer_fresh_int_tys: Vec<_> = (0..NUM_PREINTERNED_INFER_FRESH_INT_TYS)
.map(|n| mk(Infer(ty::FreshIntTy(n))))
.collect();
let infer_fresh_float_tys: Vec<_> = (0..NUM_PREINTERNED_INFER_FRESH_FLOAT_TYS)
.map(|n| mk(Infer(ty::FreshFloatTy(n))))
.collect();

let anon_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_I)
let bound_bound_anons = (0..NUM_PREINTERNED_BOUND_BOUND_ANONS_I)
.map(|i| {
(0..NUM_PREINTERNED_ANON_BOUND_TYS_V)
(0..NUM_PREINTERNED_BOUND_BOUND_ANONS_V)
.map(|v| {
mk(ty::Bound(
ty::BoundVarIndexKind::Bound(ty::DebruijnIndex::from(i)),
Expand All @@ -437,7 +447,7 @@ impl<'tcx> CommonTypes<'tcx> {
})
.collect();

let anon_canonical_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_V)
let bound_canonical_anons = (0..NUM_PREINTERNED_BOUND_CANONICAL_ANONS)
.map(|v| {
mk(ty::Bound(
ty::BoundVarIndexKind::Canonical,
Expand All @@ -446,6 +456,15 @@ impl<'tcx> CommonTypes<'tcx> {
})
.collect();

let placeholder_root_anons = (0..NUM_PREINTERNED_PLACEHOLDER_ROOT_ANONS)
.map(|v| {
mk(ty::Placeholder(PlaceholderType::new_anon(
ty::UniverseIndex::ROOT,
ty::BoundVar::from(v),
)))
})
.collect();

CommonTypes {
unit: mk(Tuple(List::empty())),
bool: mk(Bool),
Expand All @@ -470,14 +489,15 @@ impl<'tcx> CommonTypes<'tcx> {
str_: mk(Str),
self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),

trait_object_dummy_self: fresh_tys[0],
trait_object_dummy_self: infer_fresh_tys[0],

ty_vars,
fresh_tys,
fresh_int_tys,
fresh_float_tys,
anon_bound_tys,
anon_canonical_bound_tys,
infer_ty_vars,
infer_fresh_tys,
infer_fresh_int_tys,
infer_fresh_float_tys,
bound_bound_anons,
bound_canonical_anons,
placeholder_root_anons,
}
}
}
Expand All @@ -493,9 +513,9 @@ impl<'tcx> CommonLifetimes<'tcx> {
let re_vars =
(0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();

let anon_re_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_I)
let re_bound_bound_anons = (0..NUM_PREINTERNED_RE_BOUND_BOUND_ANONS_I)
.map(|i| {
(0..NUM_PREINTERNED_ANON_RE_BOUNDS_V)
(0..NUM_PREINTERNED_RE_BOUND_BOUND_ANONS_V)
.map(|v| {
mk(ty::ReBound(
ty::BoundVarIndexKind::Bound(ty::DebruijnIndex::from(i)),
Expand All @@ -509,7 +529,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
})
.collect();

let anon_re_canonical_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_V)
let re_bound_canonical_anons = (0..NUM_PREINTERNED_RE_BOUND_CANONICAL_ANONS)
.map(|v| {
mk(ty::ReBound(
ty::BoundVarIndexKind::Canonical,
Expand All @@ -522,8 +542,8 @@ impl<'tcx> CommonLifetimes<'tcx> {
re_static: mk(ty::ReStatic),
re_erased: mk(ty::ReErased),
re_vars,
anon_re_bounds,
anon_re_canonical_bounds,
re_bound_bound_anons,
re_bound_canonical_anons,
}
}
}
Expand Down
27 changes: 2 additions & 25 deletions compiler/rustc_middle/src/ty/context/impl_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
ty::AliasConstKind::Anon { .. } => None,
}
}
fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind {
self.anon_const_kind(def_id)
}

fn def_span(self, def_id: DefId) -> Span {
self.def_span(def_id)
Expand Down Expand Up @@ -494,10 +491,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item))
}

fn is_adt_lang_item(self, def_id: DefId, lang_item: SolverAdtLangItem) -> bool {
self.is_lang_item(def_id, solver_adt_lang_item_to_lang_item(lang_item))
}

fn is_default_trait(self, def_id: DefId) -> bool {
self.is_default_trait(def_id)
}
Expand Down Expand Up @@ -604,10 +597,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.trait_def(trait_def_id).safety.is_unsafe()
}

fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
self.is_impl_trait_in_trait(def_id)
}

fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed {
self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string())
}
Expand Down Expand Up @@ -683,18 +672,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
})
}

fn get_anon_re_bounds_lifetime(self, idx: usize, var_idx: usize) -> Option<Region<'tcx>> {
if let Some(inner) = self.lifetimes.anon_re_bounds.get(idx) {
inner.get(var_idx).copied()
} else {
None
}
}

fn get_anon_re_canonical_bounds_lifetime(self, idx: usize) -> Option<Region<'tcx>> {
self.lifetimes.anon_re_canonical_bounds.get(idx).copied()
}

fn get_re_static_lifetime(self) -> Region<'tcx> {
self.lifetimes.re_static
}
Expand All @@ -719,7 +696,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
) -> Region<'tcx> {
// Use a pre-interned one when possible.
if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region
&& let Some(inner) = self.lifetimes.anon_re_bounds.get(debruijn.as_usize())
&& let Some(inner) = self.lifetimes.re_bound_bound_anons.get(debruijn.as_usize())
&& let Some(re) = inner.get(var.as_usize()).copied()
{
re
Expand All @@ -730,7 +707,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {

fn intern_canonical_bound(self, var: BoundVar) -> Region<'tcx> {
// Use a pre-interned one when possible.
if let Some(re) = self.lifetimes.anon_re_canonical_bounds.get(var.as_usize()).copied() {
if let Some(re) = self.lifetimes.re_bound_canonical_anons.get(var.as_usize()).copied() {
re
} else {
self.intern_region(ty::ReBound(
Expand Down
22 changes: 15 additions & 7 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ impl<'tcx> Ty<'tcx> {
pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> {
// Use a pre-interned one when possible.
tcx.types
.ty_vars
.infer_ty_vars
.get(v.as_usize())
.copied()
.unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v))))
Expand All @@ -398,7 +398,7 @@ impl<'tcx> Ty<'tcx> {
pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
// Use a pre-interned one when possible.
tcx.types
.fresh_tys
.infer_fresh_tys
.get(n as usize)
.copied()
.unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n)))
Expand All @@ -408,7 +408,7 @@ impl<'tcx> Ty<'tcx> {
pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
// Use a pre-interned one when possible.
tcx.types
.fresh_int_tys
.infer_fresh_int_tys
.get(n as usize)
.copied()
.unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n)))
Expand All @@ -418,7 +418,7 @@ impl<'tcx> Ty<'tcx> {
pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
// Use a pre-interned one when possible.
tcx.types
.fresh_float_tys
.infer_fresh_float_tys
.get(n as usize)
.copied()
.unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n)))
Expand All @@ -437,7 +437,7 @@ impl<'tcx> Ty<'tcx> {
) -> Ty<'tcx> {
// Use a pre-interned one when possible.
if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty
&& let Some(inner) = tcx.types.anon_bound_tys.get(index.as_usize())
&& let Some(inner) = tcx.types.bound_bound_anons.get(index.as_usize())
&& let Some(ty) = inner.get(var.as_usize()).copied()
{
ty
Expand All @@ -449,7 +449,7 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: BoundVar) -> Ty<'tcx> {
// Use a pre-interned one when possible.
if let Some(ty) = tcx.types.anon_canonical_bound_tys.get(var.as_usize()).copied() {
if let Some(ty) = tcx.types.bound_canonical_anons.get(var.as_usize()).copied() {
ty
} else {
Ty::new(
Expand All @@ -464,7 +464,15 @@ impl<'tcx> Ty<'tcx> {

#[inline]
pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType<'tcx>) -> Ty<'tcx> {
Ty::new(tcx, Placeholder(placeholder))
if placeholder.universe.is_root()
&& placeholder.bound.kind == ty::BoundTyKind::Anon
&& let Some(ty) =
tcx.types.placeholder_root_anons.get(placeholder.bound.var.as_usize()).copied()
{
ty
} else {
Ty::new(tcx, Placeholder(placeholder))
}
}

#[inline]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,12 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
delegate,
CanonicalizeMode::Input(CanonicalizeInputKind::Predicate),
);
rest_canonicalizer.state.variables.extend(e.variables.iter().copied());
rest_canonicalizer.state.var_kinds.extend(e.var_kinds.iter().copied());
// SAFETY: The iterated elements go straight back into a hashmap.
#[allow(rustc::potential_query_instability)]
rest_canonicalizer.state.variables.clone_from(&e.variables);
rest_canonicalizer.state.var_kinds.clone_from(&e.var_kinds);
rest_canonicalizer
.state
.variable_lookup_table
.extend(e.variable_lookup_table.iter().map(|(&arg, &idx)| (arg, idx)));
.clone_from(&e.variable_lookup_table);
(e.param_env, rest_canonicalizer)
}
})
Expand Down
Loading
Loading