@@ -290,18 +290,55 @@ fn compare_predicate_entailment<'tcx>(
290290 "method `{}` has an incompatible type for trait" ,
291291 trait_m. ident
292292 ) ;
293- if let TypeError :: ArgumentMutability ( _) = terr {
294- if let Some ( trait_err_span) = trait_err_span {
295- if let Ok ( trait_err_str) = tcx. sess . source_map ( ) . span_to_snippet ( trait_err_span)
293+ match & terr {
294+ TypeError :: ArgumentMutability ( 0 ) | TypeError :: ArgumentSorts ( _, 0 )
295+ if trait_m. fn_has_self_parameter =>
296+ {
297+ let ty = trait_sig. inputs ( ) [ 0 ] ;
298+ let sugg = match ExplicitSelf :: determine ( ty, |_| ty == impl_trait_ref. self_ty ( ) )
296299 {
300+ ExplicitSelf :: ByValue => "self" . to_owned ( ) ,
301+ ExplicitSelf :: ByReference ( _, hir:: Mutability :: Not ) => "&self" . to_owned ( ) ,
302+ ExplicitSelf :: ByReference ( _, hir:: Mutability :: Mut ) => {
303+ "&mut self" . to_owned ( )
304+ }
305+ _ => format ! ( "self: {}" , ty) ,
306+ } ;
307+
308+ // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
309+ // span points only at the type `Box<Self`>, but we want to cover the whole
310+ // argument pattern and type.
311+ let impl_m_hir_id =
312+ tcx. hir ( ) . local_def_id_to_hir_id ( impl_m. def_id . expect_local ( ) ) ;
313+ let span = match tcx. hir ( ) . expect_impl_item ( impl_m_hir_id) . kind {
314+ ImplItemKind :: Fn ( ref sig, body) => tcx
315+ . hir ( )
316+ . body_param_names ( body)
317+ . zip ( sig. decl . inputs . iter ( ) )
318+ . map ( |( param, ty) | param. span . to ( ty. span ) )
319+ . next ( )
320+ . unwrap_or ( impl_err_span) ,
321+ _ => bug ! ( "{:?} is not a method" , impl_m) ,
322+ } ;
323+
324+ diag. span_suggestion (
325+ span,
326+ "change the self-receiver type to match the trait" ,
327+ sugg,
328+ Applicability :: MachineApplicable ,
329+ ) ;
330+ }
331+ TypeError :: ArgumentMutability ( i) | TypeError :: ArgumentSorts ( _, i) => {
332+ if let Some ( trait_ty) = trait_sig. inputs ( ) . get ( * i) {
297333 diag. span_suggestion (
298334 impl_err_span,
299- "consider changing the mutability to match the trait" ,
300- trait_err_str ,
335+ "change the parameter type to match the trait" ,
336+ trait_ty . to_string ( ) ,
301337 Applicability :: MachineApplicable ,
302338 ) ;
303339 }
304340 }
341+ _ => { }
305342 }
306343
307344 infcx. note_type_err (
@@ -482,8 +519,7 @@ fn compare_self_type<'tcx>(
482519 tcx. sess,
483520 impl_m_span,
484521 E0186 ,
485- "method `{}` has a `{}` declaration in the trait, but \
486- not in the impl",
522+ "method `{}` has a `{}` declaration in the trait, but not in the impl" ,
487523 trait_m. ident,
488524 self_descr
489525 ) ;
0 commit comments