Skip to content

Commit

Permalink
Improve "associated type not defined" diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
ShE3py committed Sep 8, 2023
1 parent 1e746d7 commit 6967af0
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 22 deletions.
53 changes: 42 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,34 @@ 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, just list them all.

if all_candidate_names.is_empty() {
err.help(format!(
"`{ty_param_name}` has no associated type, try removing `{assoc_name}`"
));
return err.emit();
}

let msg = if all_candidate_names.len() > 1 {
format!("`{ty_param_name}` has the following associated types")
} else {
format!("`{ty_param_name}` has the following associated type")
};

let applicability = if self.tcx().features().associated_type_defaults {
Applicability::Unspecified // `type A = Self::B` would suggest `type A = Self::A`
} else {
Applicability::MaybeIncorrect
};

err.span_suggestions(
assoc_name.span,
msg,
all_candidate_names.iter().map(|symbol| symbol.to_string()),
applicability,
);

err.emit()
}

Expand Down
12 changes: 9 additions & 3 deletions tests/ui/associated-consts/assoc-const-eq-missing.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@ error[E0220]: associated type `Z` not found for `Foo`
--> $DIR/assoc-const-eq-missing.rs:15:16
|
LL | fn foo1<F: Foo<Z=3>>() {}
| ^ associated type `Z` not found
| ^
|
= help: `Foo` has no associated type, try removing `Z`

error[E0220]: associated type `Z` not found for `Foo`
--> $DIR/assoc-const-eq-missing.rs:17:16
|
LL | fn foo2<F: Foo<Z=usize>>() {}
| ^ associated type `Z` not found
| ^
|
= help: `Foo` has no associated type, try removing `Z`

error[E0220]: associated type `Z` not found for `Foo`
--> $DIR/assoc-const-eq-missing.rs:19:16
|
LL | fn foo3<F: Foo<Z=5>>() {}
| ^ associated type `Z` not found
| ^
|
= help: `Foo` has no associated type, try removing `Z`

error: aborting due to 3 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ error[E0220]: associated type `Item` not found for `M`
--> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8
|
LL | M::Item: Temp,
| ^^^^ associated type `Item` not found
| ^^^^
|
= help: `M` has no associated type, try removing `Item`

error: aborting due to 2 previous errors

Expand Down
4 changes: 3 additions & 1 deletion tests/ui/associated-types/associated-types-path-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0220]: associated type `A` not found for `T`
--> $DIR/associated-types-path-1.rs:10:26
|
LL | pub fn f1<T>(a: T, x: T::A) {}
| ^ associated type `A` not found
| ^
|
= help: `T` has no associated type, try removing `A`

error[E0221]: ambiguous associated type `A` in bounds of `T`
--> $DIR/associated-types-path-1.rs:11:34
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
--> $DIR/feature-gate-return_type_notation.rs:14:17
|
LL | fn foo<T: Trait<m(): Send>>() {}
| ^ associated type `m` not found
| ^
|
= help: `Trait` has no associated type, try removing `m`

error: aborting due to 3 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
--> $DIR/feature-gate-return_type_notation.rs:17:17
|
LL | fn foo<T: Trait<m(): Send>>() {}
| ^ associated type `m` not found
| ^
|
= help: `Trait` has no associated type, try removing `m`

error: aborting due to 3 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
--> $DIR/feature-gate-return_type_notation.rs:17:17
|
LL | fn foo<T: Trait<m(): Send>>() {}
| ^ associated type `m` not found
| ^
|
= help: `Trait` has no associated type, try removing `m`

error: aborting due to 3 previous errors

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 6967af0

Please sign in to comment.