about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2025-09-08 11:41:43 +0200
committerlcnr <rust@lcnr.de>2025-09-08 14:17:56 +0200
commitb51a3a565a056235f3864e2cefdb9449f6b0dcb1 (patch)
tree525669b67e94ecdfe97995123eb4f79886831f2d
parentf51458640840cb94c32f1e55431b1c855ca22e88 (diff)
downloadrust-b51a3a565a056235f3864e2cefdb9449f6b0dcb1.tar.gz
rust-b51a3a565a056235f3864e2cefdb9449f6b0dcb1.zip
review
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs8
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs5
-rw-r--r--compiler/rustc_infer/src/infer/context.rs8
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs2
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs41
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs8
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs2
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs4
12 files changed, 57 insertions, 40 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index be68609502a..3c5e4a91c98 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -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)
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 517331c3245..f99f228e19d 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -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!()
                     }
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index b76931caaa5..14cc590720a 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -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) {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 48dd699cd50..9d3886aff1c 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -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 {
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 2323add0b32..f0b5b164a0b 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -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.
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index 613e5a5883a..65f77fe8e25 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -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.
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index d42c62439f6..a8f2b4e8db6 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -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)
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index f0f95e53265..71f9481d5af 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -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)]
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 91b83e6cbbe..db3460c4ff6 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -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)
             }
             _ => {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index dff1311070c..edab530590b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -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,
                 }
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index 44230624ddb..16f444486a6 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -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,
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index 7fec869f100..56962b4597b 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -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);