From 13a83cb6397e19088ff7d5946f901c6e35f12374 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 11 Feb 2026 17:38:34 +0900 Subject: [PATCH] Shallow resolve ty and const vars to their root vars --- compiler/rustc_infer/src/infer/mod.rs | 52 ++++++++++++++----- .../rustc_infer/src/infer/type_variable.rs | 19 +++++++ 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e15b25500bb5..21f486a228da 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1099,22 +1099,45 @@ impl<'tcx> InferCtxt<'tcx> { // // Note: if these two lines are combined into one we get // dynamic borrow errors on `self.inner`. - let known = self.inner.borrow_mut().type_variables().probe(v).known(); - known.map_or(ty, |t| self.shallow_resolve(t)) + let (root_vid, value) = + self.inner.borrow_mut().type_variables().probe_with_root_vid(v); + value.known().map_or_else( + || if root_vid == v { ty } else { Ty::new_var(self.tcx, root_vid) }, + |t| self.shallow_resolve(t), + ) } ty::IntVar(v) => { - match self.inner.borrow_mut().int_unification_table().probe_value(v) { + let (root, value) = + self.inner.borrow_mut().int_unification_table().inlined_probe_key_value(v); + match value { ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty), ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty), - ty::IntVarValue::Unknown => ty, + ty::IntVarValue::Unknown => { + if root == v { + ty + } else { + Ty::new_int_var(self.tcx, root) + } + } } } ty::FloatVar(v) => { - match self.inner.borrow_mut().float_unification_table().probe_value(v) { + let (root, value) = self + .inner + .borrow_mut() + .float_unification_table() + .inlined_probe_key_value(v); + match value { ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty), - ty::FloatVarValue::Unknown => ty, + ty::FloatVarValue::Unknown => { + if root == v { + ty + } else { + Ty::new_float_var(self.tcx, root) + } + } } } @@ -1128,13 +1151,16 @@ impl<'tcx> InferCtxt<'tcx> { pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(infer_ct) => match infer_ct { - InferConst::Var(vid) => self - .inner - .borrow_mut() - .const_unification_table() - .probe_value(vid) - .known() - .unwrap_or(ct), + InferConst::Var(vid) => { + let (root, value) = self + .inner + .borrow_mut() + .const_unification_table() + .inlined_probe_key_value(vid); + value.known().unwrap_or_else(|| { + if root.vid == vid { ct } else { ty::Const::new_var(self.tcx, root.vid) } + }) + } InferConst::Fresh(_) => ct, }, ty::ConstKind::Param(_) diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 65f77fe8e25f..9b928cc5cc8c 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -258,6 +258,25 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { self.eq_relations().inlined_probe_value(vid) } + /// Retrieves the type to which `vid` has been instantiated, if + /// any, along with the root `vid`. + pub(crate) fn probe_with_root_vid( + &mut self, + vid: ty::TyVid, + ) -> (ty::TyVid, TypeVariableValue<'tcx>) { + self.inlined_probe_with_vid(vid) + } + + /// An always-inlined variant of `probe_with_root_vid`, for very hot call sites. + #[inline(always)] + pub(crate) fn inlined_probe_with_vid( + &mut self, + vid: ty::TyVid, + ) -> (ty::TyVid, TypeVariableValue<'tcx>) { + let (id, value) = self.eq_relations().inlined_probe_key_value(vid); + (id.vid, value) + } + #[inline] fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> { self.storage.eq_relations.with_log(self.undo_log)