This commit is contained in:
lcnr 2024-10-02 14:39:43 +02:00
parent a7b114420c
commit 1a04a317c4
5 changed files with 31 additions and 23 deletions

View File

@ -14,14 +14,16 @@ use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
/// Enforce that `a` is equal to or a subtype of `b`.
pub struct TypeRelating<'combine, 'a, 'tcx> {
// Partially mutable.
// Immutable except for the `InferCtxt` and the
// resulting nested `goals`.
fields: &'combine mut CombineFields<'a, 'tcx>,
// Immutable fields.
// Immutable field.
structurally_relate_aliases: StructurallyRelateAliases,
// Mutable field.
ambient_variance: ty::Variance,
/// The cache has only tracks the `ambient_variance` as its the
/// The cache only tracks the `ambient_variance` as it's the
/// only field which is mutable and which meaningfully changes
/// the result when relating types.
///

View File

@ -210,16 +210,17 @@ where
debug_assert!(!ty.has_vars_bound_above(ty::INNERMOST));
ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32())
}
_ if t.has_vars_bound_at_or_above(self.current_index) => {
if let Some(&ty) = self.cache.get(&(self.current_index, t)) {
return ty;
_ => {
if !t.has_vars_bound_at_or_above(self.current_index) {
t
} else if let Some(&t) = self.cache.get(&(self.current_index, t)) {
t
} else {
let res = t.super_fold_with(self);
assert!(self.cache.insert((self.current_index, t), res));
res
}
let res = t.super_fold_with(self);
assert!(self.cache.insert((self.current_index, t), res));
res
}
_ => t,
}
}

View File

@ -42,17 +42,19 @@ pub enum CanonicalizeMode {
pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
delegate: &'a D,
// Immutable field.
canonicalize_mode: CanonicalizeMode,
// Mutable fields.
variables: &'a mut Vec<I::GenericArg>,
variable_lookup_table: HashMap<I::GenericArg, usize>,
primitive_var_infos: Vec<CanonicalVarInfo<I>>,
variable_lookup_table: HashMap<I::GenericArg, usize>,
binder_index: ty::DebruijnIndex,
/// We only use the debruijn index during lookup as all other fields
/// should not be impacted by whether a type is folded once or multiple
/// times.
/// We only use the debruijn index during lookup. We don't need to
/// track the `variables` as each generic arg only results in a single
/// bound variable regardless of how many times it is encountered.
cache: HashMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
}

View File

@ -16,6 +16,8 @@ where
I: Interner,
{
delegate: &'a D,
/// We're able to use a cache here as the folder does not have any
/// mutable state.
cache: DelayedMap<I::Ty, I::Ty>,
}

View File

@ -1057,16 +1057,17 @@ where
);
infer_ty
}
_ if ty.has_aliases() => {
if let Some(&entry) = self.cache.get(&ty) {
_ => {
if !ty.has_aliases() {
ty
} else if let Some(&entry) = self.cache.get(&ty) {
return entry;
} else {
let res = ty.super_fold_with(self);
assert!(self.cache.insert(ty, res).is_none());
res
}
let res = ty.super_fold_with(self);
assert!(self.cache.insert(ty, res).is_none());
res
}
_ => ty,
}
}