@@ -110,16 +110,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
110
110
{
111
111
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
112
112
// 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
+
114
115
let mut err = struct_span_err ! (
115
116
self . tcx( ) . sess,
116
- span,
117
+ if is_dummy { span } else { assoc_name . span } ,
117
118
E0220 ,
118
119
"associated type `{}` not found for `{}`" ,
119
120
assoc_name,
120
121
ty_param_name
121
122
) ;
122
123
124
+ if is_dummy {
125
+ err. span_label ( span, format ! ( "associated type `{assoc_name}` not found" ) ) ;
126
+ return err. emit ( ) ;
127
+ }
128
+
123
129
let all_candidate_names: Vec < _ > = all_candidates ( )
124
130
. flat_map ( |r| self . tcx ( ) . associated_items ( r. def_id ( ) ) . in_definition_order ( ) )
125
131
. filter_map ( |item| {
@@ -131,10 +137,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
131
137
} )
132
138
. collect ( ) ;
133
139
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
+ {
138
143
err. span_suggestion (
139
144
assoc_name. span ,
140
145
"there is an associated type with a similar name" ,
@@ -172,10 +177,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
172
177
} )
173
178
. collect ( ) ;
174
179
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
+ {
179
183
if let [ best_trait] = visible_traits
180
184
. iter ( )
181
185
. filter ( |trait_def_id| {
@@ -197,7 +201,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
197
201
}
198
202
}
199
203
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
+
201
232
err. emit ( )
202
233
}
203
234
0 commit comments