Rollup merge of #115662 - ShE3py:E0220-note, r=compiler-errors

Improve "associated type not found" diagnostics

```rs
use core::ops::Deref;

fn foo<T>() where T: Deref<Output = u32> {}
```

Before:
```
error[E0220]: associated type `Output` not found for `Deref`
 --> E0220.rs:5:28
  |
5 | fn foo<T>() where T: Deref<Output = u32> {}
  |                            ^^^^^^ associated type `Output` not found
```

After:
```
error[E0220]: associated type `Output` not found for `Deref`
 --> E0220.rs:5:28
  |
5 | fn foo<T>() where T: Deref<Output = u32> {}
  |                            ^^^^^^ help: `Deref` has the following associated type: `Target`
```

---

`@rustbot` label +A-diagnostics +D-papercut
This commit is contained in:
Matthias Krüger 2023-09-09 00:28:20 +02:00 committed by GitHub
commit 69044a1693
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 14 deletions

View File

@ -110,16 +110,22 @@ pub(crate) fn complain_about_assoc_type_not_found<I>(
{ {
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
// valid span, so we point at the whole path segment instead. // valid span, so we point at the whole path segment instead.
let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span }; let is_dummy = assoc_name.span == DUMMY_SP;
let mut err = struct_span_err!( let mut err = struct_span_err!(
self.tcx().sess, self.tcx().sess,
span, if is_dummy { span } else { assoc_name.span },
E0220, E0220,
"associated type `{}` not found for `{}`", "associated type `{}` not found for `{}`",
assoc_name, assoc_name,
ty_param_name ty_param_name
); );
if is_dummy {
err.span_label(span, format!("associated type `{assoc_name}` not found"));
return err.emit();
}
let all_candidate_names: Vec<_> = all_candidates() let all_candidate_names: Vec<_> = all_candidates()
.flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
.filter_map(|item| { .filter_map(|item| {
@ -131,10 +137,9 @@ pub(crate) fn complain_about_assoc_type_not_found<I>(
}) })
.collect(); .collect();
if let (Some(suggested_name), true) = ( if let Some(suggested_name) =
find_best_match_for_name(&all_candidate_names, assoc_name.name, None), find_best_match_for_name(&all_candidate_names, assoc_name.name, None)
assoc_name.span != DUMMY_SP, {
) {
err.span_suggestion( err.span_suggestion(
assoc_name.span, assoc_name.span,
"there is an associated type with a similar name", "there is an associated type with a similar name",
@ -172,10 +177,9 @@ pub(crate) fn complain_about_assoc_type_not_found<I>(
}) })
.collect(); .collect();
if let (Some(suggested_name), true) = ( if let Some(suggested_name) =
find_best_match_for_name(&wider_candidate_names, assoc_name.name, None), find_best_match_for_name(&wider_candidate_names, assoc_name.name, None)
assoc_name.span != DUMMY_SP, {
) {
if let [best_trait] = visible_traits if let [best_trait] = visible_traits
.iter() .iter()
.filter(|trait_def_id| { .filter(|trait_def_id| {
@ -197,7 +201,28 @@ pub(crate) fn complain_about_assoc_type_not_found<I>(
} }
} }
err.span_label(span, format!("associated type `{assoc_name}` not found")); // If we still couldn't find any associated type, and only one associated type exists,
// suggests using it.
if all_candidate_names.len() == 1 {
// this should still compile, except on `#![feature(associated_type_defaults)]`
// where it could suggests `type A = Self::A`, thus recursing infinitely
let applicability = if self.tcx().features().associated_type_defaults {
Applicability::Unspecified
} else {
Applicability::MaybeIncorrect
};
err.span_suggestion(
assoc_name.span,
format!("`{ty_param_name}` has the following associated type"),
all_candidate_names.first().unwrap().to_string(),
applicability,
);
} else {
err.span_label(assoc_name.span, format!("associated type `{assoc_name}` not found"));
}
err.emit() err.emit()
} }

View File

@ -2,7 +2,7 @@ error[E0220]: associated type `anything_here_kills_it` not found for `Self`
--> $DIR/issue-23595-2.rs:6:22 --> $DIR/issue-23595-2.rs:6:22
| |
LL | type B = C<Self::anything_here_kills_it>; LL | type B = C<Self::anything_here_kills_it>;
| ^^^^^^^^^^^^^^^^^^^^^^ associated type `anything_here_kills_it` not found | ^^^^^^^^^^^^^^^^^^^^^^ help: `Self` has the following associated type: `B`
error: aborting due to previous error error: aborting due to previous error

View File

@ -2,7 +2,7 @@ error[E0220]: associated type `F` not found for `Trait`
--> $DIR/E0220.rs:5:22 --> $DIR/E0220.rs:5:22
| |
LL | type Foo = dyn Trait<F=i32>; LL | type Foo = dyn Trait<F=i32>;
| ^ associated type `F` not found | ^ help: `Trait` has the following associated type: `Bar`
error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must be specified error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must be specified
--> $DIR/E0220.rs:5:16 --> $DIR/E0220.rs:5:16

View File

@ -36,7 +36,7 @@ error[E0220]: associated type `B` not found for `Self`
--> $DIR/issue-95023.rs:6:44 --> $DIR/issue-95023.rs:6:44
| |
LL | fn foo<const N: usize>(&self) -> Self::B<{N}>; LL | fn foo<const N: usize>(&self) -> Self::B<{N}>;
| ^ associated type `B` not found | ^ help: `Self` has the following associated type: `Output`
error: aborting due to 5 previous errors error: aborting due to 5 previous errors