@@ -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
0 commit comments