@@ -278,9 +278,8 @@ fn compare_predicate_entailment<'tcx>(
278
278
if let Err ( terr) = sub_result {
279
279
debug ! ( "sub_types failed: impl ty {:?}, trait ty {:?}" , impl_fty, trait_fty) ;
280
280
281
- let ( impl_err_span, trait_err_span) = extract_spans_for_error_reporting (
282
- & infcx, param_env, & terr, & cause, impl_m, impl_sig, trait_m, trait_sig,
283
- ) ;
281
+ let ( impl_err_span, trait_err_span) =
282
+ extract_spans_for_error_reporting ( & infcx, & terr, & cause, impl_m, trait_m) ;
284
283
285
284
cause. make_mut ( ) . span = impl_err_span;
286
285
@@ -291,18 +290,79 @@ fn compare_predicate_entailment<'tcx>(
291
290
"method `{}` has an incompatible type for trait" ,
292
291
trait_m. ident
293
292
) ;
294
- if let TypeError :: Mutability = terr {
295
- if let Some ( trait_err_span) = trait_err_span {
296
- 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 ( ) )
297
299
{
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 trait_sig. inputs ( ) . len ( ) == * i {
333
+ // Suggestion to change output type. We do not suggest in `async` functions
334
+ // to avoid complex logic or incorrect output.
335
+ let impl_m_hir_id =
336
+ tcx. hir ( ) . local_def_id_to_hir_id ( impl_m. def_id . expect_local ( ) ) ;
337
+ match tcx. hir ( ) . expect_impl_item ( impl_m_hir_id) . kind {
338
+ ImplItemKind :: Fn ( ref sig, _)
339
+ if sig. header . asyncness == hir:: IsAsync :: NotAsync =>
340
+ {
341
+ let msg = "change the output type to match the trait" ;
342
+ let ap = Applicability :: MachineApplicable ;
343
+ match sig. decl . output {
344
+ hir:: FnRetTy :: DefaultReturn ( sp) => {
345
+ let sugg = format ! ( "-> {} " , trait_sig. output( ) ) ;
346
+ diag. span_suggestion_verbose ( sp, msg, sugg, ap) ;
347
+ }
348
+ hir:: FnRetTy :: Return ( hir_ty) => {
349
+ let sugg = trait_sig. output ( ) . to_string ( ) ;
350
+ diag. span_suggestion ( hir_ty. span , msg, sugg, ap) ;
351
+ }
352
+ } ;
353
+ }
354
+ _ => { }
355
+ } ;
356
+ } else if let Some ( trait_ty) = trait_sig. inputs ( ) . get ( * i) {
298
357
diag. span_suggestion (
299
358
impl_err_span,
300
- "consider changing the mutability to match the trait" ,
301
- trait_err_str ,
359
+ "change the parameter type to match the trait" ,
360
+ trait_ty . to_string ( ) ,
302
361
Applicability :: MachineApplicable ,
303
362
) ;
304
363
}
305
364
}
365
+ _ => { }
306
366
}
307
367
308
368
infcx. note_type_err (
@@ -385,86 +445,35 @@ fn check_region_bounds_on_impl_item<'tcx>(
385
445
386
446
fn extract_spans_for_error_reporting < ' a , ' tcx > (
387
447
infcx : & infer:: InferCtxt < ' a , ' tcx > ,
388
- param_env : ty:: ParamEnv < ' tcx > ,
389
448
terr : & TypeError < ' _ > ,
390
449
cause : & ObligationCause < ' tcx > ,
391
450
impl_m : & ty:: AssocItem ,
392
- impl_sig : ty:: FnSig < ' tcx > ,
393
451
trait_m : & ty:: AssocItem ,
394
- trait_sig : ty:: FnSig < ' tcx > ,
395
452
) -> ( Span , Option < Span > ) {
396
453
let tcx = infcx. tcx ;
397
454
let impl_m_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( impl_m. def_id . expect_local ( ) ) ;
398
- let ( impl_m_output , impl_m_iter ) = match tcx. hir ( ) . expect_impl_item ( impl_m_hir_id) . kind {
399
- ImplItemKind :: Fn ( ref impl_m_sig , _) => {
400
- ( & impl_m_sig . decl . output , impl_m_sig . decl . inputs . iter ( ) )
455
+ let mut impl_args = match tcx. hir ( ) . expect_impl_item ( impl_m_hir_id) . kind {
456
+ ImplItemKind :: Fn ( ref sig , _) => {
457
+ sig . decl . inputs . iter ( ) . map ( |t| t . span ) . chain ( iter :: once ( sig . decl . output . span ( ) ) )
401
458
}
402
459
_ => bug ! ( "{:?} is not a method" , impl_m) ,
403
460
} ;
404
-
405
- match * terr {
406
- TypeError :: Mutability => {
407
- if let Some ( def_id) = trait_m. def_id . as_local ( ) {
408
- let trait_m_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
409
- let trait_m_iter = match tcx. hir ( ) . expect_trait_item ( trait_m_hir_id) . kind {
410
- TraitItemKind :: Fn ( ref trait_m_sig, _) => trait_m_sig. decl . inputs . iter ( ) ,
411
- _ => bug ! ( "{:?} is not a TraitItemKind::Fn" , trait_m) ,
412
- } ;
413
-
414
- iter:: zip ( impl_m_iter, trait_m_iter)
415
- . find ( |& ( ref impl_arg, ref trait_arg) | {
416
- match ( & impl_arg. kind , & trait_arg. kind ) {
417
- (
418
- & hir:: TyKind :: Rptr ( _, ref impl_mt) ,
419
- & hir:: TyKind :: Rptr ( _, ref trait_mt) ,
420
- )
421
- | ( & hir:: TyKind :: Ptr ( ref impl_mt) , & hir:: TyKind :: Ptr ( ref trait_mt) ) => {
422
- impl_mt. mutbl != trait_mt. mutbl
423
- }
424
- _ => false ,
425
- }
426
- } )
427
- . map ( |( ref impl_arg, ref trait_arg) | ( impl_arg. span , Some ( trait_arg. span ) ) )
428
- . unwrap_or_else ( || ( cause. span ( tcx) , tcx. hir ( ) . span_if_local ( trait_m. def_id ) ) )
429
- } else {
430
- ( cause. span ( tcx) , tcx. hir ( ) . span_if_local ( trait_m. def_id ) )
461
+ let trait_args = trait_m. def_id . as_local ( ) . map ( |def_id| {
462
+ let trait_m_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
463
+ match tcx. hir ( ) . expect_trait_item ( trait_m_hir_id) . kind {
464
+ TraitItemKind :: Fn ( ref sig, _) => {
465
+ sig. decl . inputs . iter ( ) . map ( |t| t. span ) . chain ( iter:: once ( sig. decl . output . span ( ) ) )
431
466
}
467
+ _ => bug ! ( "{:?} is not a TraitItemKind::Fn" , trait_m) ,
432
468
}
433
- TypeError :: Sorts ( ExpectedFound { .. } ) => {
434
- if let Some ( def_id) = trait_m. def_id . as_local ( ) {
435
- let trait_m_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
436
- let ( trait_m_output, trait_m_iter) =
437
- match tcx. hir ( ) . expect_trait_item ( trait_m_hir_id) . kind {
438
- TraitItemKind :: Fn ( ref trait_m_sig, _) => {
439
- ( & trait_m_sig. decl . output , trait_m_sig. decl . inputs . iter ( ) )
440
- }
441
- _ => bug ! ( "{:?} is not a TraitItemKind::Fn" , trait_m) ,
442
- } ;
469
+ } ) ;
443
470
444
- let impl_iter = impl_sig. inputs ( ) . iter ( ) ;
445
- let trait_iter = trait_sig. inputs ( ) . iter ( ) ;
446
- iter:: zip ( iter:: zip ( impl_iter, trait_iter) , iter:: zip ( impl_m_iter, trait_m_iter) )
447
- . find_map ( |( ( & impl_arg_ty, & trait_arg_ty) , ( impl_arg, trait_arg) ) | match infcx
448
- . at ( & cause, param_env)
449
- . sub ( trait_arg_ty, impl_arg_ty)
450
- {
451
- Ok ( _) => None ,
452
- Err ( _) => Some ( ( impl_arg. span , Some ( trait_arg. span ) ) ) ,
453
- } )
454
- . unwrap_or_else ( || {
455
- if infcx
456
- . at ( & cause, param_env)
457
- . sup ( trait_sig. output ( ) , impl_sig. output ( ) )
458
- . is_err ( )
459
- {
460
- ( impl_m_output. span ( ) , Some ( trait_m_output. span ( ) ) )
461
- } else {
462
- ( cause. span ( tcx) , tcx. hir ( ) . span_if_local ( trait_m. def_id ) )
463
- }
464
- } )
465
- } else {
466
- ( cause. span ( tcx) , tcx. hir ( ) . span_if_local ( trait_m. def_id ) )
467
- }
471
+ match * terr {
472
+ TypeError :: ArgumentMutability ( i) => {
473
+ ( impl_args. nth ( i) . unwrap ( ) , trait_args. and_then ( |mut args| args. nth ( i) ) )
474
+ }
475
+ TypeError :: ArgumentSorts ( ExpectedFound { .. } , i) => {
476
+ ( impl_args. nth ( i) . unwrap ( ) , trait_args. and_then ( |mut args| args. nth ( i) ) )
468
477
}
469
478
_ => ( cause. span ( tcx) , tcx. hir ( ) . span_if_local ( trait_m. def_id ) ) ,
470
479
}
@@ -514,8 +523,7 @@ fn compare_self_type<'tcx>(
514
523
tcx. sess,
515
524
impl_m_span,
516
525
E0185 ,
517
- "method `{}` has a `{}` declaration in the impl, but \
518
- not in the trait",
526
+ "method `{}` has a `{}` declaration in the impl, but not in the trait" ,
519
527
trait_m. ident,
520
528
self_descr
521
529
) ;
@@ -535,8 +543,7 @@ fn compare_self_type<'tcx>(
535
543
tcx. sess,
536
544
impl_m_span,
537
545
E0186 ,
538
- "method `{}` has a `{}` declaration in the trait, but \
539
- not in the impl",
546
+ "method `{}` has a `{}` declaration in the trait, but not in the impl" ,
540
547
trait_m. ident,
541
548
self_descr
542
549
) ;
@@ -993,8 +1000,7 @@ crate fn compare_const_impl<'tcx>(
993
1000
tcx. sess,
994
1001
cause. span,
995
1002
E0326 ,
996
- "implemented const `{}` has an incompatible type for \
997
- trait",
1003
+ "implemented const `{}` has an incompatible type for trait" ,
998
1004
trait_c. ident
999
1005
) ;
1000
1006
0 commit comments