Skip to content

Commit

Permalink
Rollup merge of #115662 - ShE3py:E0220-note, r=compiler-errors
Browse files Browse the repository at this point in the history
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
  • Loading branch information
matthiaskrgr committed Sep 8, 2023
2 parents b33ac52 + a0e0a32 commit 69044a1
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 14 deletions.
47 changes: 36 additions & 11 deletions compiler/rustc_hir_analysis/src/astconv/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
{
// 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.
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!(
self.tcx().sess,
span,
if is_dummy { span } else { assoc_name.span },
E0220,
"associated type `{}` not found for `{}`",
assoc_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()
.flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
.filter_map(|item| {
Expand All @@ -131,10 +137,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
})
.collect();

if let (Some(suggested_name), true) = (
find_best_match_for_name(&all_candidate_names, assoc_name.name, None),
assoc_name.span != DUMMY_SP,
) {
if let Some(suggested_name) =
find_best_match_for_name(&all_candidate_names, assoc_name.name, None)
{
err.span_suggestion(
assoc_name.span,
"there is an associated type with a similar name",
Expand Down Expand Up @@ -172,10 +177,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
})
.collect();

if let (Some(suggested_name), true) = (
find_best_match_for_name(&wider_candidate_names, assoc_name.name, None),
assoc_name.span != DUMMY_SP,
) {
if let Some(suggested_name) =
find_best_match_for_name(&wider_candidate_names, assoc_name.name, None)
{
if let [best_trait] = visible_traits
.iter()
.filter(|trait_def_id| {
Expand All @@ -197,7 +201,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}

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()
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/associated-types/issue-23595-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0220]: associated type `anything_here_kills_it` not found for `Self`
--> $DIR/issue-23595-2.rs:6:22
|
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

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/error-codes/E0220.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0220]: associated type `F` not found for `Trait`
--> $DIR/E0220.rs:5:22
|
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
--> $DIR/E0220.rs:5:16
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lifetimes/issue-95023.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ error[E0220]: associated type `B` not found for `Self`
--> $DIR/issue-95023.rs:6:44
|
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

Expand Down

0 comments on commit 69044a1

Please sign in to comment.