review
This commit is contained in:
@@ -294,6 +294,12 @@ struct Canonicalizer<'cx, 'tcx> {
|
||||
// Note that indices is only used once `var_values` is big enough to be
|
||||
// heap-allocated.
|
||||
indices: FxHashMap<GenericArg<'tcx>, BoundVar>,
|
||||
/// Maps each `sub_unification_table_root_var` to the index of the first
|
||||
/// variable which used it.
|
||||
///
|
||||
/// This means in case two type variables have the same sub relations root,
|
||||
/// 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: SsoHashMap<ty::TyVid, usize>,
|
||||
canonicalize_mode: &'cx dyn CanonicalizeMode,
|
||||
needs_canonical_flags: TypeFlags,
|
||||
@@ -662,7 +668,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
|
||||
let root_vid = self.infcx.unwrap().sub_root_var(vid);
|
||||
let root_vid = self.infcx.unwrap().sub_unification_table_root_var(vid);
|
||||
let idx =
|
||||
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
|
||||
ty::BoundVar::from(idx)
|
||||
|
||||
@@ -93,10 +93,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
match kind {
|
||||
CanonicalVarKind::Ty { ui, sub_root } => {
|
||||
let vid = self.next_ty_vid_in_universe(span, universe_map(ui));
|
||||
// Fetch the `sub_root` in case it exists.
|
||||
// If this inference variable is related to an earlier variable
|
||||
// via subtyping, we need to add that info to the inference context.
|
||||
if let Some(prev) = previous_var_values.get(sub_root.as_usize()) {
|
||||
if let &ty::Infer(ty::TyVar(sub_root)) = prev.expect_ty().kind() {
|
||||
self.inner.borrow_mut().type_variables().sub(vid, sub_root);
|
||||
self.sub_unify_ty_vids_raw(vid, sub_root);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||
self.root_var(var)
|
||||
}
|
||||
|
||||
fn sub_root_ty_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_root_var(var)
|
||||
fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_unification_table_root_var(var)
|
||||
}
|
||||
|
||||
fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
|
||||
@@ -183,8 +183,8 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||
self.inner.borrow_mut().type_variables().equate(a, b);
|
||||
}
|
||||
|
||||
fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.sub_ty_vids_raw(a, b);
|
||||
fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.sub_unify_ty_vids_raw(a, b);
|
||||
}
|
||||
|
||||
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) {
|
||||
|
||||
@@ -764,7 +764,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let r_b = self.shallow_resolve(predicate.skip_binder().b);
|
||||
match (r_a.kind(), r_b.kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.sub_ty_vids_raw(a_vid, b_vid);
|
||||
self.sub_unify_ty_vids_raw(a_vid, b_vid);
|
||||
return Err((a_vid, b_vid));
|
||||
}
|
||||
_ => {}
|
||||
@@ -1129,12 +1129,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.inner.borrow_mut().type_variables().root_var(var)
|
||||
}
|
||||
|
||||
pub fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.inner.borrow_mut().type_variables().sub(a, b);
|
||||
pub fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.inner.borrow_mut().type_variables().sub_unify(a, b);
|
||||
}
|
||||
|
||||
pub fn sub_root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
self.inner.borrow_mut().type_variables().sub_root_var(var)
|
||||
pub fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
self.inner.borrow_mut().type_variables().sub_unification_table_root_var(var)
|
||||
}
|
||||
|
||||
pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
|
||||
|
||||
@@ -522,7 +522,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
|
||||
// Record that `vid` and `new_var_id` have to be subtypes
|
||||
// of each other. This is currently only used for diagnostics.
|
||||
// To see why, see the docs in the `type_variables` module.
|
||||
inner.type_variables().sub(vid, new_var_id);
|
||||
inner.type_variables().sub_unify(vid, new_var_id);
|
||||
// If we're in the new solver and create a new inference
|
||||
// variable inside of an alias we eagerly constrain that
|
||||
// inference variable to prevent unexpected ambiguity errors.
|
||||
|
||||
@@ -42,7 +42,7 @@ impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for TypeVariabl
|
||||
|
||||
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidSubKey>>> for TypeVariableStorage<'tcx> {
|
||||
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidSubKey>>) {
|
||||
self.sub_relations.reverse(undo)
|
||||
self.sub_unification_table.reverse(undo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
|
||||
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||
match undo {
|
||||
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
|
||||
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
|
||||
UndoLog::SubRelation(undo) => self.sub_unification_table.reverse(undo),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,9 @@ pub(crate) struct TypeVariableStorage<'tcx> {
|
||||
/// constraint `?X == ?Y`. This table also stores, for each key,
|
||||
/// the known value.
|
||||
eq_relations: ut::UnificationTableStorage<TyVidEqKey<'tcx>>,
|
||||
/// Only used by `-Znext-solver` and for diagnostics.
|
||||
/// Only used by `-Znext-solver` and for diagnostics. Tracks whether
|
||||
/// type variables are related via subtyping at all, ignoring which of
|
||||
/// the two is the subtype.
|
||||
///
|
||||
/// When reporting ambiguity errors, we sometimes want to
|
||||
/// treat all inference vars which are subtypes of each
|
||||
@@ -79,7 +81,7 @@ pub(crate) struct TypeVariableStorage<'tcx> {
|
||||
/// Even for something like `let x = returns_arg(); x.method();` the
|
||||
/// type of `x` is only a supertype of the argument of `returns_arg`. We
|
||||
/// still want to suggest specifying the type of the argument.
|
||||
sub_relations: ut::UnificationTableStorage<TyVidSubKey>,
|
||||
sub_unification_table: ut::UnificationTableStorage<TyVidSubKey>,
|
||||
}
|
||||
|
||||
pub(crate) struct TypeVariableTable<'a, 'tcx> {
|
||||
@@ -155,23 +157,24 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
self.storage.values[vid].origin
|
||||
}
|
||||
|
||||
/// Records that `a == b`, depending on `dir`.
|
||||
/// Records that `a == b`.
|
||||
///
|
||||
/// Precondition: neither `a` nor `b` are known.
|
||||
pub(crate) fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||
debug_assert!(self.probe(a).is_unknown());
|
||||
debug_assert!(self.probe(b).is_unknown());
|
||||
self.eq_relations().union(a, b);
|
||||
self.sub_relations().union(a, b);
|
||||
self.sub_unification_table().union(a, b);
|
||||
}
|
||||
|
||||
/// Records that `a <: b`, depending on `dir`.
|
||||
/// Records that `a` and `b` are related via subtyping. We don't track
|
||||
/// which of the two is the subtype.
|
||||
///
|
||||
/// Precondition: neither `a` nor `b` are known.
|
||||
pub(crate) fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||
pub(crate) fn sub_unify(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||
debug_assert!(self.probe(a).is_unknown());
|
||||
debug_assert!(self.probe(b).is_unknown());
|
||||
self.sub_relations().union(a, b);
|
||||
self.sub_unification_table().union(a, b);
|
||||
}
|
||||
|
||||
/// Instantiates `vid` with the type `ty`.
|
||||
@@ -206,7 +209,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
) -> ty::TyVid {
|
||||
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
|
||||
|
||||
let sub_key = self.sub_relations().new_key(());
|
||||
let sub_key = self.sub_unification_table().new_key(());
|
||||
debug_assert_eq!(eq_key.vid, sub_key.vid);
|
||||
|
||||
let index = self.storage.values.push(TypeVariableData { origin });
|
||||
@@ -231,16 +234,16 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
self.eq_relations().find(vid).vid
|
||||
}
|
||||
|
||||
/// Returns the "root" variable of `vid` in the `sub_relations`
|
||||
/// equivalence table. All type variables that have been are
|
||||
/// related via equality or subtyping will yield the same root
|
||||
/// variable (per the union-find algorithm), so `sub_root_var(a)
|
||||
/// == sub_root_var(b)` implies that:
|
||||
/// Returns the "root" variable of `vid` in the `sub_unification_table`
|
||||
/// equivalence table. All type variables that have been are related via
|
||||
/// equality or subtyping will yield the same root variable (per the
|
||||
/// union-find algorithm), so `sub_unification_table_root_var(a)
|
||||
/// == sub_unification_table_root_var(b)` implies that:
|
||||
/// ```text
|
||||
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
|
||||
/// ```
|
||||
pub(crate) fn sub_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_relations().find(vid).vid
|
||||
pub(crate) fn sub_unification_table_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_unification_table().find(vid).vid
|
||||
}
|
||||
|
||||
/// Retrieves the type to which `vid` has been instantiated, if
|
||||
@@ -261,8 +264,8 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidSubKey> {
|
||||
self.storage.sub_relations.with_log(self.undo_log)
|
||||
fn sub_unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidSubKey> {
|
||||
self.storage.sub_unification_table.with_log(self.undo_log)
|
||||
}
|
||||
|
||||
/// Returns a range of the type variables created during the snapshot.
|
||||
|
||||
@@ -67,6 +67,12 @@ pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
|
||||
variables: &'a mut Vec<I::GenericArg>,
|
||||
var_kinds: Vec<CanonicalVarKind<I>>,
|
||||
variable_lookup_table: HashMap<I::GenericArg, usize>,
|
||||
/// Maps each `sub_unification_table_root_var` to the index of the first
|
||||
/// variable which used it.
|
||||
///
|
||||
/// This means in case two type variables have the same sub relations root,
|
||||
/// 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,
|
||||
|
||||
@@ -273,7 +279,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
||||
}
|
||||
|
||||
fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
|
||||
let root_vid = self.delegate.sub_root_ty_var(vid);
|
||||
let root_vid = self.delegate.sub_unification_table_root_var(vid);
|
||||
let idx =
|
||||
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
|
||||
ty::BoundVar::from(idx)
|
||||
|
||||
@@ -900,8 +900,8 @@ where
|
||||
&& goal.param_env.visit_with(&mut visitor).is_continue()
|
||||
}
|
||||
|
||||
pub(super) fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.delegate.sub_ty_vids_raw(a, b)
|
||||
pub(super) fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.delegate.sub_unify_ty_vids_raw(a, b)
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||
|
||||
@@ -121,7 +121,7 @@ where
|
||||
fn compute_subtype_goal(&mut self, goal: Goal<I, ty::SubtypePredicate<I>>) -> QueryResult<I> {
|
||||
match (goal.predicate.a.kind(), goal.predicate.b.kind()) {
|
||||
(ty::Infer(ty::TyVar(a_vid)), ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.sub_ty_vids_raw(a_vid, b_vid);
|
||||
self.sub_unify_ty_vids_raw(a_vid, b_vid);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
}
|
||||
_ => {
|
||||
|
||||
@@ -894,7 +894,8 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
||||
use ty::{Infer, TyVar};
|
||||
match (inner_ty.kind(), target_ty.kind()) {
|
||||
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
|
||||
self.tecx.sub_root_var(a_vid) == self.tecx.sub_root_var(b_vid)
|
||||
self.tecx.sub_unification_table_root_var(a_vid)
|
||||
== self.tecx.sub_unification_table_root_var(b_vid)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
| ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
|
||||
match (self.shallow_resolve(a).kind(), self.shallow_resolve(b).kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.sub_ty_vids_raw(a_vid, b_vid);
|
||||
self.sub_unify_ty_vids_raw(a_vid, b_vid);
|
||||
Some(Certainty::AMBIGUOUS)
|
||||
}
|
||||
_ => None,
|
||||
|
||||
@@ -158,7 +158,7 @@ pub trait InferCtxtLike: Sized {
|
||||
fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
|
||||
|
||||
fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
|
||||
fn sub_root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
|
||||
fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
|
||||
fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
|
||||
|
||||
fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
|
||||
@@ -198,7 +198,7 @@ pub trait InferCtxtLike: Sized {
|
||||
) -> U;
|
||||
|
||||
fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
|
||||
fn sub_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
|
||||
fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
|
||||
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
|
||||
fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
|
||||
fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
|
||||
|
||||
Reference in New Issue
Block a user