From 79033b095f53bba1d77f1730c00cc7565da293b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Mon, 6 Jul 2026 14:23:18 +0200 Subject: [PATCH 1/9] add tests and demonstrate them working before changes --- .../fudge-eager-resolve-breakage-1.rs | 12 ++++++++++++ .../fudge-eager-resolve-breakage-2.rs | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-1.rs create mode 100644 tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-2.rs diff --git a/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-1.rs b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-1.rs new file mode 100644 index 0000000000000..eb0333491b0d3 --- /dev/null +++ b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-1.rs @@ -0,0 +1,12 @@ +//@ build-pass +//@ compile-flags: --crate-type lib +pub trait Trait { + type Assoc; + fn create_from(_: F) -> Self::Assoc; +} + +fn map(_: T::Assoc) {} + +pub fn traverse() { + map::(T::create_from(|| ())); +} diff --git a/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-2.rs b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-2.rs new file mode 100644 index 0000000000000..d26f2238b4896 --- /dev/null +++ b/tests/ui/coercion/fudge-inference/fudge-eager-resolve-breakage-2.rs @@ -0,0 +1,19 @@ +//@ build-pass +#[expect(dead_code)] + +// Must be invariant +pub struct Server(*mut T); +impl Server { + fn new(_: T) -> Self + where + // Must be higher-ranked + T: Fn(&mut i32), + { + todo!() + } +} + +fn main() { + // Must have a type annotation + let _: Server<_> = Server::new(|_| ()); +} From 9d301e8a98aa9795b9c5ff76bf38ad4af372c130 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 11 Feb 2026 17:38:34 +0900 Subject: [PATCH 2/9] Shallow resolve ty and const vars to their root vars --- compiler/rustc_infer/src/infer/mod.rs | 52 ++++++++++++++++++++------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9c1907bbe8401..653552c2623f4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1247,22 +1247,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) + } + } } } @@ -1276,13 +1299,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, }, From 49cfe7f7a1e876ef00b05056e2fec6607db83378 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 11 Feb 2026 17:50:50 +0900 Subject: [PATCH 3/9] Remove redundant `shallow_resolve` call --- compiler/rustc_infer/src/infer/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 653552c2623f4..dfa15f4c14768 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1333,6 +1333,13 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().root_var(var) } + /// If `ty` is an unresolved type variable, returns its root vid. + pub fn root_vid(&self, ty: Ty<'tcx>) -> Option { + let (root, value) = + self.inner.borrow_mut().type_variables().inlined_probe_with_vid(ty.ty_vid()?); + value.is_unknown().then_some(root) + } + pub fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { self.inner.borrow_mut().type_variables().sub_unify(a, b); } From e50bdff7cbf930960f731c7267975932277af3ae Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 11 Feb 2026 18:00:36 +0900 Subject: [PATCH 4/9] Bless tests --- .../incremental/const-generics/issue-64087.rs | 2 - .../inference-fail.stderr | 2 +- .../warn-when-cycle-is-error-in-coherence.rs | 2 +- ...rn-when-cycle-is-error-in-coherence.stderr | 2 +- .../dyn-compatibility-ok-infer-err.rs | 1 - .../dyn-compatibility-ok-infer-err.stderr | 23 +- tests/ui/const-generics/infer/issue-77092.rs | 1 - .../const-generics/infer/issue-77092.stderr | 20 +- .../try-from-with-const-genericsrs-98299.rs | 2 - ...ry-from-with-const-genericsrs-98299.stderr | 44 +-- .../multiline-removal-suggestion.svg | 364 ++++++++++-------- .../indexing/indexing-requires-a-uint.stderr | 2 - .../point-at-index-for-obligation-failure.rs | 4 +- ...int-at-index-for-obligation-failure.stderr | 9 +- tests/ui/parser/issue-12187-1.stderr | 2 +- tests/ui/parser/issue-12187-2.stderr | 2 +- ...opy-inference-side-effects-are-lazy.stderr | 2 +- .../suggest-dereferencing-index.stderr | 2 - ...oxed-closures-failed-recursive-fn-2.stderr | 2 +- 19 files changed, 225 insertions(+), 263 deletions(-) diff --git a/tests/incremental/const-generics/issue-64087.rs b/tests/incremental/const-generics/issue-64087.rs index c316f787cc932..1377d05706f2e 100644 --- a/tests/incremental/const-generics/issue-64087.rs +++ b/tests/incremental/const-generics/issue-64087.rs @@ -6,6 +6,4 @@ fn combinator() -> [T; S] {} fn main() { combinator().into_iter(); //[bfail1]~^ ERROR type annotations needed - //[bfail1]~| ERROR type annotations needed - //[bfail1]~| ERROR type annotations needed } diff --git a/tests/ui/associated-inherent-types/inference-fail.stderr b/tests/ui/associated-inherent-types/inference-fail.stderr index bf329c69e99c1..12cc3ae7960c6 100644 --- a/tests/ui/associated-inherent-types/inference-fail.stderr +++ b/tests/ui/associated-inherent-types/inference-fail.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/inference-fail.rs:10:12 | LL | let _: S<_>::P = (); - | ^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^ cannot infer type error: aborting due to 1 previous error diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs index c50bbcec52157..b754b1cb54728 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs @@ -3,7 +3,7 @@ use std::cmp::Ordering; use std::marker::PhantomData; #[derive(PartialEq, Default)] -//~^ ERROR conflicting implementations of trait `PartialEq>` for type `Interval<_>` +//~^ ERROR conflicting implementations of trait `PartialEq` for type `Interval<_>` pub(crate) struct Interval(PhantomData); // This impl overlaps with the `derive` unless we reject the nested diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr index a9a99fb28d844..620694aacf83b 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `PartialEq>` for type `Interval<_>` +error[E0119]: conflicting implementations of trait `PartialEq` for type `Interval<_>` --> $DIR/warn-when-cycle-is-error-in-coherence.rs:5:10 | LL | #[derive(PartialEq, Default)] diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs index 298cfb512e418..79e9834b54ed2 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs @@ -18,5 +18,4 @@ fn use_dyn(v: &dyn Foo) where [u8; N + 1]: Sized { fn main() { use_dyn(&()); //~^ ERROR type annotations needed - //~| ERROR type annotations needed } diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr index d66623e792635..51a9c6f1d177c 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr @@ -14,27 +14,6 @@ help: consider specifying a const for the const parameter `N` LL | use_dyn::(&()); | +++++++++++++++ -error[E0284]: type annotations needed - --> $DIR/dyn-compatibility-ok-infer-err.rs:19:5 - | -LL | use_dyn(&()); - | ^^^^^^^ --- type must be known at this point - | | - | cannot infer the value of the const parameter `N` declared on the function `use_dyn` - | -note: required for `()` to implement `Foo<_>` - --> $DIR/dyn-compatibility-ok-infer-err.rs:8:22 - | -LL | impl Foo for () { - | -------------- ^^^^^^ ^^ - | | - | unsatisfied trait bound introduced here - = note: required for the cast from `&()` to `&dyn Foo<_>` -help: consider specifying a const for the const parameter `N` - | -LL | use_dyn::(&()); - | +++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/infer/issue-77092.rs b/tests/ui/const-generics/infer/issue-77092.rs index 47c594e5b11ea..77d1fe187795d 100644 --- a/tests/ui/const-generics/infer/issue-77092.rs +++ b/tests/ui/const-generics/infer/issue-77092.rs @@ -10,6 +10,5 @@ fn main() { for i in 1..4 { println!("{:?}", take_array_from_mut(&mut arr, i)); //~^ ERROR type annotations needed - //~| ERROR type annotations needed } } diff --git a/tests/ui/const-generics/infer/issue-77092.stderr b/tests/ui/const-generics/infer/issue-77092.stderr index 3763cd738a861..96f6496eca537 100644 --- a/tests/ui/const-generics/infer/issue-77092.stderr +++ b/tests/ui/const-generics/infer/issue-77092.stderr @@ -14,24 +14,6 @@ help: consider specifying the generic arguments LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); | ++++++++++ -error[E0284]: type annotations needed - --> $DIR/issue-77092.rs:11:26 - | -LL | println!("{:?}", take_array_from_mut(&mut arr, i)); - | ---- ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `take_array_from_mut` - | | - | required by this formatting parameter - | - = note: required for `[i32; _]` to implement `Debug` - = note: 1 redundant requirement hidden - = note: required for `&mut [i32; _]` to implement `Debug` -note: required by a bound in `core::fmt::rt::Argument::<'_>::new_debug` - --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL -help: consider specifying the generic arguments - | -LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); - | ++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs index 49c88856bc96a..808d960da68b7 100644 --- a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs +++ b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.rs @@ -4,8 +4,6 @@ use std::convert::TryFrom; pub fn test_usage(p: ()) { SmallCString::try_from(p).map(|cstr| cstr); //~^ ERROR: type annotations needed - //~| ERROR: type annotations needed - //~| ERROR: type annotations needed } pub struct SmallCString {} diff --git a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr index 1557b83b00ec7..c80efd6df8a89 100644 --- a/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr +++ b/tests/ui/const-generics/try-from-with-const-genericsrs-98299.stderr @@ -7,7 +7,7 @@ LL | SmallCString::try_from(p).map(|cstr| cstr); | type must be known at this point | note: required by a const generic parameter in `SmallCString` - --> $DIR/try-from-with-const-genericsrs-98299.rs:11:25 + --> $DIR/try-from-with-const-genericsrs-98299.rs:9:25 | LL | pub struct SmallCString {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `SmallCString` @@ -16,46 +16,6 @@ help: consider giving this closure parameter an explicit type, where the value o LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); | +++++++++++++++++ -error[E0284]: type annotations needed for `SmallCString<_>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:5:36 - | -LL | SmallCString::try_from(p).map(|cstr| cstr); - | ------------ ^^^^ - | | - | type must be known at this point - | -note: required for `SmallCString<_>` to implement `TryFrom<()>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:13:22 - | -LL | impl TryFrom<()> for SmallCString { - | -------------- ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ - | | - | unsatisfied trait bound introduced here -help: consider giving this closure parameter an explicit type, where the value of const parameter `N` is specified - | -LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); - | +++++++++++++++++ - -error[E0284]: type annotations needed for `SmallCString<_>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:5:36 - | -LL | SmallCString::try_from(p).map(|cstr| cstr); - | ------------------------- ^^^^ - | | - | type must be known at this point - | -note: required for `SmallCString<_>` to implement `TryFrom<()>` - --> $DIR/try-from-with-const-genericsrs-98299.rs:13:22 - | -LL | impl TryFrom<()> for SmallCString { - | -------------- ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ - | | - | unsatisfied trait bound introduced here -help: consider giving this closure parameter an explicit type, where the value of const parameter `N` is specified - | -LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); - | +++++++++++++++++ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/error-emitter/multiline-removal-suggestion.svg b/tests/ui/error-emitter/multiline-removal-suggestion.svg index de54859821b82..5c47481d4c178 100644 --- a/tests/ui/error-emitter/multiline-removal-suggestion.svg +++ b/tests/ui/error-emitter/multiline-removal-suggestion.svg @@ -1,4 +1,4 @@ - +