Skip to content

Commit 66c506d

Browse files
authored
Rollup merge of #153921 - arferreira:fix-bogus-assoc-type-constraint-suggestion, r=estebank
Suppress self-referential associated type constraint suggestion Fixes #112104 When comparing `Option<&I::Item>` against `Option<I::Item>`, the compiler decomposes the mismatch into `expected = &<I as Iterator>::Item` vs `found = <I as Iterator>::Item`. ARM 2 in `note_and_explain_type_err` matches because `found` is a projection, and would suggest `Item = &<I as Iterator>::Item` — constraining the associated type to something that contains itself. ARM 1 (`expected_projection`) already guards against this with `found.contains(expected)`. ARM 2 was missing the symmetric check. This adds `expected.contains(found)` to the match guard. Before: ```rust help: consider constraining the associated type `<I as Iterator>::Item` to `&<I as Iterator>::Item` | 1 | fn foo<I: Iterator<Item = &<I as Iterator>::Item>>(iter: &mut I) { | +++++++++++++++++++++++++++++++ ``` After: bogus suggestion is gone, and the existing `.as_ref()` suggestion from `hir_typeck` still fires correctly. r? @estebank
2 parents deb6627 + 4ecc78d commit 66c506d

3 files changed

Lines changed: 59 additions & 1 deletion

File tree

compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,13 @@ impl<T> Trait<T> for X {
263263
cause.code(),
264264
);
265265
}
266+
// Don't suggest constraining a projection to something
267+
// containing itself, e.g. `Item = &<I as Iterator>::Item`.
266268
(_, ty::Alias(ty::Projection | ty::Inherent, proj_ty))
267-
if !tcx.is_impl_trait_in_trait(proj_ty.def_id) =>
269+
if !tcx.is_impl_trait_in_trait(proj_ty.def_id)
270+
&& !tcx
271+
.erase_and_anonymize_regions(values.expected)
272+
.contains(tcx.erase_and_anonymize_regions(values.found)) =>
268273
{
269274
let msg = || {
270275
format!(
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Regression test for #112104.
2+
//
3+
// Don't suggest `Item = &<I as Iterator>::Item` when
4+
// the expected type wraps the found projection.
5+
6+
fn option_of_ref_assoc<I: Iterator>(iter: &mut I) {
7+
let _: Option<&I::Item> = iter.next();
8+
//~^ ERROR mismatched types
9+
}
10+
11+
// Valid constraint suggestions should still fire.
12+
trait Foo {
13+
type Assoc;
14+
}
15+
16+
fn assoc_to_concrete<T: Foo>(x: T::Assoc) -> u32 {
17+
x //~ ERROR mismatched types
18+
}
19+
20+
fn main() {}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/dont-suggest-self-referential-constraint.rs:7:31
3+
|
4+
LL | let _: Option<&I::Item> = iter.next();
5+
| ---------------- ^^^^^^^^^^^ expected `Option<&<I as Iterator>::Item>`, found `Option<<I as Iterator>::Item>`
6+
| |
7+
| expected due to this
8+
|
9+
= note: expected enum `Option<&_>`
10+
found enum `Option<_>`
11+
help: try using `.as_ref()` to convert `Option<<I as Iterator>::Item>` to `Option<&<I as Iterator>::Item>`
12+
|
13+
LL | let _: Option<&I::Item> = iter.next().as_ref();
14+
| +++++++++
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/dont-suggest-self-referential-constraint.rs:17:5
18+
|
19+
LL | fn assoc_to_concrete<T: Foo>(x: T::Assoc) -> u32 {
20+
| --- expected `u32` because of return type
21+
LL | x
22+
| ^ expected `u32`, found associated type
23+
|
24+
= note: expected type `u32`
25+
found associated type `<T as Foo>::Assoc`
26+
help: consider constraining the associated type `<T as Foo>::Assoc` to `u32`
27+
|
28+
LL | fn assoc_to_concrete<T: Foo<Assoc = u32>>(x: T::Assoc) -> u32 {
29+
| +++++++++++++
30+
31+
error: aborting due to 2 previous errors
32+
33+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)