Skip to content

Commit 96c9664

Browse files
committed
Improve "associated type not found" diagnostics
1 parent 1e746d7 commit 96c9664

10 files changed

+69
-22
lines changed

compiler/rustc_hir_analysis/src/astconv/errors.rs

+42-11
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
110110
{
111111
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
112112
// valid span, so we point at the whole path segment instead.
113-
let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span };
113+
let is_dummy = assoc_name.span == DUMMY_SP;
114+
114115
let mut err = struct_span_err!(
115116
self.tcx().sess,
116-
span,
117+
if is_dummy { span } else { assoc_name.span },
117118
E0220,
118119
"associated type `{}` not found for `{}`",
119120
assoc_name,
120121
ty_param_name
121122
);
122123

124+
if is_dummy {
125+
err.span_label(span, format!("associated type `{assoc_name}` not found"));
126+
return err.emit();
127+
}
128+
123129
let all_candidate_names: Vec<_> = all_candidates()
124130
.flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
125131
.filter_map(|item| {
@@ -131,10 +137,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
131137
})
132138
.collect();
133139

134-
if let (Some(suggested_name), true) = (
135-
find_best_match_for_name(&all_candidate_names, assoc_name.name, None),
136-
assoc_name.span != DUMMY_SP,
137-
) {
140+
if let Some(suggested_name) =
141+
find_best_match_for_name(&all_candidate_names, assoc_name.name, None)
142+
{
138143
err.span_suggestion(
139144
assoc_name.span,
140145
"there is an associated type with a similar name",
@@ -172,10 +177,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
172177
})
173178
.collect();
174179

175-
if let (Some(suggested_name), true) = (
176-
find_best_match_for_name(&wider_candidate_names, assoc_name.name, None),
177-
assoc_name.span != DUMMY_SP,
178-
) {
180+
if let Some(suggested_name) =
181+
find_best_match_for_name(&wider_candidate_names, assoc_name.name, None)
182+
{
179183
if let [best_trait] = visible_traits
180184
.iter()
181185
.filter(|trait_def_id| {
@@ -197,7 +201,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
197201
}
198202
}
199203

200-
err.span_label(span, format!("associated type `{assoc_name}` not found"));
204+
// If we still couldn't find any associated type, just list them all.
205+
206+
if all_candidate_names.is_empty() {
207+
err.help(format!(
208+
"`{ty_param_name}` has no associated type, try removing `{assoc_name}`"
209+
));
210+
return err.emit();
211+
}
212+
213+
let msg = if all_candidate_names.len() > 1 {
214+
format!("`{ty_param_name}` has the following associated types")
215+
} else {
216+
format!("`{ty_param_name}` has the following associated type")
217+
};
218+
219+
let applicability = if self.tcx().features().associated_type_defaults {
220+
Applicability::Unspecified // `type A = Self::B` would suggest `type A = Self::A`
221+
} else {
222+
Applicability::MaybeIncorrect
223+
};
224+
225+
err.span_suggestions(
226+
assoc_name.span,
227+
msg,
228+
all_candidate_names.iter().map(|symbol| symbol.to_string()),
229+
applicability,
230+
);
231+
201232
err.emit()
202233
}
203234

tests/ui/associated-consts/assoc-const-eq-missing.stderr

+9-3
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,25 @@ error[E0220]: associated type `Z` not found for `Foo`
22
--> $DIR/assoc-const-eq-missing.rs:15:16
33
|
44
LL | fn foo1<F: Foo<Z=3>>() {}
5-
| ^ associated type `Z` not found
5+
| ^
6+
|
7+
= help: `Foo` has no associated type, try removing `Z`
68

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

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

1925
error: aborting due to 3 previous errors
2026

tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ error[E0220]: associated type `Item` not found for `M`
88
--> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8
99
|
1010
LL | M::Item: Temp,
11-
| ^^^^ associated type `Item` not found
11+
| ^^^^
12+
|
13+
= help: `M` has no associated type, try removing `Item`
1214

1315
error: aborting due to 2 previous errors
1416

tests/ui/associated-types/associated-types-path-1.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0220]: associated type `A` not found for `T`
22
--> $DIR/associated-types-path-1.rs:10:26
33
|
44
LL | pub fn f1<T>(a: T, x: T::A) {}
5-
| ^ associated type `A` not found
5+
| ^
6+
|
7+
= help: `T` has no associated type, try removing `A`
68

79
error[E0221]: ambiguous associated type `A` in bounds of `T`
810
--> $DIR/associated-types-path-1.rs:11:34

tests/ui/associated-types/issue-23595-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0220]: associated type `anything_here_kills_it` not found for `Self`
22
--> $DIR/issue-23595-2.rs:6:22
33
|
44
LL | type B = C<Self::anything_here_kills_it>;
5-
| ^^^^^^^^^^^^^^^^^^^^^^ associated type `anything_here_kills_it` not found
5+
| ^^^^^^^^^^^^^^^^^^^^^^ help: `Self` has the following associated type: `B`
66

77
error: aborting due to previous error
88

tests/ui/error-codes/E0220.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0220]: associated type `F` not found for `Trait`
22
--> $DIR/E0220.rs:5:22
33
|
44
LL | type Foo = dyn Trait<F=i32>;
5-
| ^ associated type `F` not found
5+
| ^ help: `Trait` has the following associated type: `Bar`
66

77
error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must be specified
88
--> $DIR/E0220.rs:5:16

tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
1919
--> $DIR/feature-gate-return_type_notation.rs:14:17
2020
|
2121
LL | fn foo<T: Trait<m(): Send>>() {}
22-
| ^ associated type `m` not found
22+
| ^
23+
|
24+
= help: `Trait` has no associated type, try removing `m`
2325

2426
error: aborting due to 3 previous errors
2527

tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
1919
--> $DIR/feature-gate-return_type_notation.rs:17:17
2020
|
2121
LL | fn foo<T: Trait<m(): Send>>() {}
22-
| ^ associated type `m` not found
22+
| ^
23+
|
24+
= help: `Trait` has no associated type, try removing `m`
2325

2426
error: aborting due to 3 previous errors
2527

tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
1919
--> $DIR/feature-gate-return_type_notation.rs:17:17
2020
|
2121
LL | fn foo<T: Trait<m(): Send>>() {}
22-
| ^ associated type `m` not found
22+
| ^
23+
|
24+
= help: `Trait` has no associated type, try removing `m`
2325

2426
error: aborting due to 3 previous errors
2527

tests/ui/lifetimes/issue-95023.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ error[E0220]: associated type `B` not found for `Self`
3636
--> $DIR/issue-95023.rs:6:44
3737
|
3838
LL | fn foo<const N: usize>(&self) -> Self::B<{N}>;
39-
| ^ associated type `B` not found
39+
| ^ help: `Self` has the following associated type: `Output`
4040

4141
error: aborting due to 5 previous errors
4242

0 commit comments

Comments
 (0)