diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 0fde0009debe7..7f53fdbc2c9f8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -263,8 +263,13 @@ impl Trait for X { cause.code(), ); } + // Don't suggest constraining a projection to something + // containing itself, e.g. `Item = &::Item`. (_, ty::Alias(ty::Projection | ty::Inherent, proj_ty)) - if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => + if !tcx.is_impl_trait_in_trait(proj_ty.def_id) + && !tcx + .erase_and_anonymize_regions(values.expected) + .contains(tcx.erase_and_anonymize_regions(values.found)) => { let msg = || { format!( diff --git a/tests/ui/associated-types/dont-suggest-self-referential-constraint.rs b/tests/ui/associated-types/dont-suggest-self-referential-constraint.rs new file mode 100644 index 0000000000000..ad999a1c77356 --- /dev/null +++ b/tests/ui/associated-types/dont-suggest-self-referential-constraint.rs @@ -0,0 +1,20 @@ +// Regression test for #112104. +// +// Don't suggest `Item = &::Item` when +// the expected type wraps the found projection. + +fn option_of_ref_assoc(iter: &mut I) { + let _: Option<&I::Item> = iter.next(); + //~^ ERROR mismatched types +} + +// Valid constraint suggestions should still fire. +trait Foo { + type Assoc; +} + +fn assoc_to_concrete(x: T::Assoc) -> u32 { + x //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/associated-types/dont-suggest-self-referential-constraint.stderr b/tests/ui/associated-types/dont-suggest-self-referential-constraint.stderr new file mode 100644 index 0000000000000..e6e37cdf7e515 --- /dev/null +++ b/tests/ui/associated-types/dont-suggest-self-referential-constraint.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-self-referential-constraint.rs:7:31 + | +LL | let _: Option<&I::Item> = iter.next(); + | ---------------- ^^^^^^^^^^^ expected `Option<&::Item>`, found `Option<::Item>` + | | + | expected due to this + | + = note: expected enum `Option<&_>` + found enum `Option<_>` +help: try using `.as_ref()` to convert `Option<::Item>` to `Option<&::Item>` + | +LL | let _: Option<&I::Item> = iter.next().as_ref(); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/dont-suggest-self-referential-constraint.rs:17:5 + | +LL | fn assoc_to_concrete(x: T::Assoc) -> u32 { + | --- expected `u32` because of return type +LL | x + | ^ expected `u32`, found associated type + | + = note: expected type `u32` + found associated type `::Assoc` +help: consider constraining the associated type `::Assoc` to `u32` + | +LL | fn assoc_to_concrete>(x: T::Assoc) -> u32 { + | +++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.