yeet CanonicalVarInfo

This commit is contained in:
lcnr
2025-05-23 10:12:55 +00:00
parent 52bf0cf795
commit 326b7e9a6b
18 changed files with 208 additions and 250 deletions

View File

@@ -4,8 +4,8 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
use rustc_type_ir::inherent::*;
use rustc_type_ir::solve::{Goal, QueryInput};
use rustc_type_ir::{
self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, InferCtxtLike,
Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, InferCtxtLike, Interner,
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use crate::delegate::SolverDelegate;
@@ -50,7 +50,7 @@ pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
// Mutable fields.
variables: &'a mut Vec<I::GenericArg>,
primitive_var_infos: Vec<CanonicalVarInfo<I>>,
var_kinds: Vec<CanonicalVarKind<I>>,
variable_lookup_table: HashMap<I::GenericArg, usize>,
binder_index: ty::DebruijnIndex,
@@ -73,7 +73,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variables,
variable_lookup_table: Default::default(),
primitive_var_infos: Vec::new(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
@@ -106,7 +106,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variables,
variable_lookup_table: Default::default(),
primitive_var_infos: Vec::new(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
@@ -123,7 +123,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
// We're able to reuse the `variable_lookup_table` as whether or not
// it already contains an entry for `'static` does not matter.
variable_lookup_table: env_canonicalizer.variable_lookup_table,
primitive_var_infos: env_canonicalizer.primitive_var_infos,
var_kinds: env_canonicalizer.var_kinds,
binder_index: ty::INNERMOST,
// We do not reuse the cache as it may contain entries whose canonicalized
@@ -149,7 +149,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
fn get_or_insert_bound_var(
&mut self,
arg: impl Into<I::GenericArg>,
canonical_var_info: CanonicalVarInfo<I>,
kind: CanonicalVarKind<I>,
) -> ty::BoundVar {
// FIXME: 16 is made up and arbitrary. We should look at some
// perf data here.
@@ -162,14 +162,14 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
*self.variable_lookup_table.entry(arg).or_insert_with(|| {
let var = self.variables.len();
self.variables.push(arg);
self.primitive_var_infos.push(canonical_var_info);
self.var_kinds.push(kind);
var
})
} else {
self.variables.iter().position(|&v| v == arg).unwrap_or_else(|| {
let var = self.variables.len();
self.variables.push(arg);
self.primitive_var_infos.push(canonical_var_info);
self.var_kinds.push(kind);
var
})
};
@@ -177,8 +177,8 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
ty::BoundVar::from(idx)
}
fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) {
let mut var_infos = self.primitive_var_infos;
fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVarKinds) {
let mut var_kinds = self.var_kinds;
// See the rustc-dev-guide section about how we deal with universes
// during canonicalization in the new solver.
match self.canonicalize_mode {
@@ -192,25 +192,25 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
// information for placeholders and inference variables created inside
// of the query.
CanonicalizeMode::Response { max_input_universe } => {
for var in var_infos.iter_mut() {
for var in var_kinds.iter_mut() {
let uv = var.universe();
let new_uv = ty::UniverseIndex::from(
uv.index().saturating_sub(max_input_universe.index()),
);
*var = var.with_updated_universe(new_uv);
}
let max_universe = var_infos
let max_universe = var_kinds
.iter()
.map(|info| info.universe())
.map(|kind| kind.universe())
.max()
.unwrap_or(ty::UniverseIndex::ROOT);
let var_infos = self.delegate.cx().mk_canonical_var_infos(&var_infos);
return (max_universe, var_infos);
let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&var_kinds);
return (max_universe, var_kinds);
}
}
// Given a `var_infos` with existentials `En` and universals `Un` in
// Given a `var_kinds` with existentials `En` and universals `Un` in
// universes `n`, this algorithm compresses them in place so that:
//
// - the new universe indices are as small as possible
@@ -219,12 +219,12 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
// 2. put a placeholder in the same universe as an existential which cannot name it
//
// Let's walk through an example:
// - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
// - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
// - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
// - var_infos: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
// - var_infos: [E0, U1, E2, U1, E1, E6, U6], curr_compressed_uv: 2, next_orig_uv: 6
// - var_infos: [E0, U1, E1, U1, E1, E3, U3], curr_compressed_uv: 2, next_orig_uv: -
// - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
// - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
// - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
// - var_kinds: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
// - var_kinds: [E0, U1, E2, U1, E1, E6, U6], curr_compressed_uv: 2, next_orig_uv: 6
// - var_kinds: [E0, U1, E1, U1, E1, E3, U3], curr_compressed_uv: 2, next_orig_uv: -
//
// This algorithm runs in `O(mn)` where `n` is the number of different universes and
// `m` the number of variables. This should be fine as both are expected to be small.
@@ -232,7 +232,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
let mut existential_in_new_uv = None;
let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
while let Some(orig_uv) = next_orig_uv.take() {
let mut update_uv = |var: &mut CanonicalVarInfo<I>, orig_uv, is_existential| {
let mut update_uv = |var: &mut CanonicalVarKind<I>, orig_uv, is_existential| {
let uv = var.universe();
match uv.cmp(&orig_uv) {
Ordering::Less => (), // Already updated
@@ -284,7 +284,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
// Whenever we compress the universe of a placeholder, no existential with
// an already compressed universe can name that placeholder.
for is_existential in [false, true] {
for var in var_infos.iter_mut() {
for var in var_kinds.iter_mut() {
// We simply put all regions from the input into the highest
// compressed universe, so we only deal with them at the end.
if !var.is_region() {
@@ -298,7 +298,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
// We put all regions into a separate universe.
let mut first_region = true;
for var in var_infos.iter_mut() {
for var in var_kinds.iter_mut() {
if var.is_region() {
if first_region {
first_region = false;
@@ -309,8 +309,8 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
}
}
let var_infos = self.delegate.cx().mk_canonical_var_infos(&var_infos);
(curr_compressed_uv, var_infos)
let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&var_kinds);
(curr_compressed_uv, var_kinds)
}
fn cached_fold_ty(&mut self, t: I::Ty) -> I::Ty {
@@ -391,7 +391,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
}
};
let var = self.get_or_insert_bound_var(t, CanonicalVarInfo { kind });
let var = self.get_or_insert_bound_var(t, kind);
Ty::new_anon_bound(self.cx(), self.binder_index, var)
}
@@ -475,7 +475,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
}
};
let var = self.get_or_insert_bound_var(r, CanonicalVarInfo { kind });
let var = self.get_or_insert_bound_var(r, kind);
Region::new_anon_bound(self.cx(), self.binder_index, var)
}
@@ -525,7 +525,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
| ty::ConstKind::Expr(_) => return c.super_fold_with(self),
};
let var = self.get_or_insert_bound_var(c, CanonicalVarInfo { kind });
let var = self.get_or_insert_bound_var(c, kind);
Const::new_anon_bound(self.cx(), self.binder_index, var)
}

View File

@@ -61,7 +61,7 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
fn instantiate_canonical_var_with_infer(
&self,
cv_info: ty::CanonicalVarInfo<Self::Interner>,
kind: ty::CanonicalVarKind<Self::Interner>,
span: <Self::Interner as Interner>::Span,
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> <Self::Interner as Interner>::GenericArg;

View File

@@ -360,15 +360,15 @@ where
}
let var_values = delegate.cx().mk_args_from_iter(
response.variables.iter().enumerate().map(|(index, info)| {
if info.universe() != ty::UniverseIndex::ROOT {
response.variables.iter().enumerate().map(|(index, var_kind)| {
if var_kind.universe() != ty::UniverseIndex::ROOT {
// A variable from inside a binder of the query. While ideally these shouldn't
// exist at all (see the FIXME at the start of this method), we have to deal with
// them for now.
delegate.instantiate_canonical_var_with_infer(info, span, |idx| {
delegate.instantiate_canonical_var_with_infer(var_kind, span, |idx| {
prev_universe + idx.index()
})
} else if info.is_existential() {
} else if var_kind.is_existential() {
// As an optimization we sometimes avoid creating a new inference variable here.
//
// All new inference variables we create start out in the current universe of the caller.
@@ -379,12 +379,13 @@ where
if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] {
v
} else {
delegate.instantiate_canonical_var_with_infer(info, span, |_| prev_universe)
delegate
.instantiate_canonical_var_with_infer(var_kind, span, |_| prev_universe)
}
} else {
// For placeholders which were already part of the input, we simply map this
// universal bound variable back the placeholder of the input.
original_values[info.expect_placeholder_index()]
original_values[var_kind.expect_placeholder_index()]
}
}),
);

View File

@@ -91,7 +91,7 @@ where
/// The variable info for the `var_values`, only used to make an ambiguous response
/// with no constraints.
variables: I::CanonicalVars,
variables: I::CanonicalVarKinds,
/// What kind of goal we're currently computing, see the enum definition
/// for more info.

View File

@@ -354,7 +354,7 @@ where
fn response_no_constraints_raw<I: Interner>(
cx: I,
max_universe: ty::UniverseIndex,
variables: I::CanonicalVars,
variables: I::CanonicalVarKinds,
certainty: Certainty,
) -> CanonicalResponse<I> {
ty::Canonical {