diff options
| author | lcnr <rust@lcnr.de> | 2025-09-08 11:41:43 +0200 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2025-09-08 14:17:56 +0200 |
| commit | b51a3a565a056235f3864e2cefdb9449f6b0dcb1 (patch) | |
| tree | 525669b67e94ecdfe97995123eb4f79886831f2d | |
| parent | f51458640840cb94c32f1e55431b1c855ca22e88 (diff) | |
| download | rust-b51a3a565a056235f3864e2cefdb9449f6b0dcb1.tar.gz rust-b51a3a565a056235f3864e2cefdb9449f6b0dcb1.zip | |
review
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); |
