Split Bound into Canonical and Bound

This commit is contained in:
jackh726
2025-09-28 23:04:55 +00:00
committed by Jack Huey
parent 6f34f4ee07
commit d1bbd39c59
45 changed files with 391 additions and 247 deletions

View File

@@ -74,12 +74,10 @@ pub(super) struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner
/// we set the `sub_root` of the second variable to the position of the first.
/// Otherwise the `sub_root` of each type variable is just its own position.
sub_root_lookup_table: HashMap<ty::TyVid, usize>,
binder_index: ty::DebruijnIndex,
/// 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>,
/// We can simply cache based on the ty itself, because we use
/// `ty::BoundVarIndexKind::Canonical`.
cache: HashMap<I::Ty, I::Ty>,
}
impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
@@ -97,7 +95,6 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table: Default::default(),
sub_root_lookup_table: Default::default(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
};
@@ -141,12 +138,10 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table: Default::default(),
sub_root_lookup_table: Default::default(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
};
let param_env = param_env.fold_with(&mut env_canonicalizer);
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
CanonicalParamEnvCacheEntry {
param_env,
@@ -175,12 +170,10 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table: Default::default(),
sub_root_lookup_table: Default::default(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
};
let param_env = param_env.fold_with(&mut env_canonicalizer);
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
(param_env, env_canonicalizer.variable_lookup_table, env_canonicalizer.var_kinds)
}
@@ -212,7 +205,6 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table,
sub_root_lookup_table: Default::default(),
var_kinds,
binder_index: ty::INNERMOST,
// We do not reuse the cache as it may contain entries whose canonicalized
// value contains `'static`. While we could alternatively handle this by
@@ -409,7 +401,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
let var = self.get_or_insert_bound_var(t, kind);
Ty::new_anon_bound(self.cx(), self.binder_index, var)
Ty::new_canonical_bound(self.cx(), var)
}
}
@@ -418,16 +410,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
self.delegate.cx()
}
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
where
T: TypeFoldable<I>,
{
self.binder_index.shift_in(1);
let t = t.super_fold_with(self);
self.binder_index.shift_out(1);
t
}
fn fold_region(&mut self, r: I::Region) -> I::Region {
let kind = match r.kind() {
ty::ReBound(..) => return r,
@@ -491,15 +473,15 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
let var = self.get_or_insert_bound_var(r, kind);
Region::new_anon_bound(self.cx(), self.binder_index, var)
Region::new_canonical_bound(self.cx(), var)
}
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
if let Some(&ty) = self.cache.get(&(self.binder_index, t)) {
if let Some(&ty) = self.cache.get(&t) {
ty
} else {
let res = self.inner_fold_ty(t);
let old = self.cache.insert((self.binder_index, t), res);
let old = self.cache.insert(t, res);
assert_eq!(old, None);
res
}
@@ -552,7 +534,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
let var = self.get_or_insert_bound_var(c, kind);
Const::new_anon_bound(self.cx(), self.binder_index, var)
Const::new_canonical_bound(self.cx(), var)
}
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {

View File

@@ -167,25 +167,25 @@ where
// and only use it for placeholders. We need to handle the
// `sub_root` of type inference variables which would make this
// more involved. They are also a lot rarer than region variables.
if let ty::Bound(debruijn, b) = t.kind()
if let ty::Bound(index_kind, b) = t.kind()
&& !matches!(
response.variables.get(b.var().as_usize()).unwrap(),
CanonicalVarKind::Ty { .. }
)
{
assert_eq!(debruijn, ty::INNERMOST);
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[b.var()] = Some(*original_value);
}
}
ty::GenericArgKind::Lifetime(r) => {
if let ty::ReBound(debruijn, br) = r.kind() {
assert_eq!(debruijn, ty::INNERMOST);
if let ty::ReBound(index_kind, br) = r.kind() {
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[br.var()] = Some(*original_value);
}
}
ty::GenericArgKind::Const(c) => {
if let ty::ConstKind::Bound(debruijn, bv) = c.kind() {
assert_eq!(debruijn, ty::INNERMOST);
if let ty::ConstKind::Bound(index_kind, bv) = c.kind() {
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[bv.var()] = Some(*original_value);
}
}

View File

@@ -90,7 +90,7 @@ where
fn fold_region(&mut self, r: I::Region) -> I::Region {
match r.kind() {
ty::ReBound(debruijn, _)
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn.as_usize()
>= self.current_index.as_usize() + self.universe_indices.len() =>
{
@@ -99,7 +99,9 @@ where
self.universe_indices
);
}
ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
if debruijn >= self.current_index =>
{
let universe = self.universe_for(debruijn);
let p = PlaceholderLike::new(universe, br);
self.mapped_regions.insert(p, br);
@@ -111,7 +113,7 @@ where
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
match t.kind() {
ty::Bound(debruijn, _)
ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn.as_usize() + 1
> self.current_index.as_usize() + self.universe_indices.len() =>
{
@@ -120,7 +122,9 @@ where
self.universe_indices
);
}
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty)
if debruijn >= self.current_index =>
{
let universe = self.universe_for(debruijn);
let p = PlaceholderLike::new(universe, bound_ty);
self.mapped_types.insert(p, bound_ty);
@@ -133,7 +137,7 @@ where
fn fold_const(&mut self, ct: I::Const) -> I::Const {
match ct.kind() {
ty::ConstKind::Bound(debruijn, _)
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn.as_usize() + 1
> self.current_index.as_usize() + self.universe_indices.len() =>
{
@@ -142,7 +146,9 @@ where
self.universe_indices
);
}
ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)
if debruijn >= self.current_index =>
{
let universe = self.universe_for(debruijn);
let p = PlaceholderLike::new(universe, bound_const);
self.mapped_consts.insert(p, bound_const);