@@ -380,7 +380,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
380
380
return ;
381
381
}
382
382
383
- let ( msg, sugg ) = match ( expected. is_ref ( ) , found. is_ref ( ) ) {
383
+ let ( msg, sug ) = match ( expected. is_ref ( ) , found. is_ref ( ) ) {
384
384
( true , false ) => {
385
385
let msg = "consider using a reference" ;
386
386
let sug = format ! ( "&{fn_name}" ) ;
@@ -404,22 +404,58 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
404
404
( msg, sug)
405
405
}
406
406
} ;
407
- diag. span_suggestion ( span, msg, & sugg , Applicability :: MaybeIncorrect ) ;
407
+ diag. span_suggestion ( span, msg, sug , Applicability :: MaybeIncorrect ) ;
408
408
}
409
409
( ty:: FnDef ( did1, substs1) , ty:: FnDef ( did2, substs2) ) => {
410
410
let expected_sig =
411
411
& ( self . normalize_fn_sig ) ( self . tcx . bound_fn_sig ( * did1) . subst ( self . tcx , substs1) ) ;
412
412
let found_sig =
413
413
& ( self . normalize_fn_sig ) ( self . tcx . bound_fn_sig ( * did2) . subst ( self . tcx , substs2) ) ;
414
414
415
- if self . same_type_modulo_infer ( * found_sig, * expected_sig) {
416
- diag. note (
417
- "different fn items have unique types, even if their signatures are the same" ,
418
- ) ;
415
+ if self . same_type_modulo_infer ( * expected_sig, * found_sig) {
416
+ diag. note ( "different fn items have unique types, even if their signatures are the same" ) ;
417
+ }
418
+
419
+ if !self . same_type_modulo_infer ( * found_sig, * expected_sig)
420
+ || !found_sig. is_suggestable ( self . tcx , true )
421
+ || !expected_sig. is_suggestable ( self . tcx , true )
422
+ || ty:: util:: is_intrinsic ( self . tcx , * did1)
423
+ || ty:: util:: is_intrinsic ( self . tcx , * did2)
424
+ {
425
+ return ;
419
426
}
427
+
428
+ let fn_name = self . tcx . def_path_str_with_substs ( * did2, substs2) ;
429
+ let sug = if found. is_ref ( ) {
430
+ format ! ( "&({fn_name} as {found_sig})" )
431
+ } else {
432
+ format ! ( "{fn_name} as {found_sig}" )
433
+ } ;
434
+
435
+ let msg = format ! (
436
+ "consider casting both fn items to fn pointers using `as {expected_sig}`"
437
+ ) ;
438
+
439
+ diag. span_suggestion_hidden ( span, msg, sug, Applicability :: MaybeIncorrect ) ;
420
440
}
421
- ( ty:: FnDef ( _, _) , ty:: FnPtr ( _) ) => {
422
- diag. note ( "fn items are distinct from fn pointers" ) ;
441
+ ( ty:: FnDef ( did, substs) , ty:: FnPtr ( sig) ) => {
442
+ let expected_sig =
443
+ & ( self . normalize_fn_sig ) ( self . tcx . bound_fn_sig ( * did) . subst ( self . tcx , substs) ) ;
444
+ let found_sig = & ( self . normalize_fn_sig ) ( * sig) ;
445
+
446
+ if !self . same_type_modulo_infer ( * found_sig, * expected_sig) {
447
+ return ;
448
+ }
449
+
450
+ let fn_name = self . tcx . def_path_str_with_substs ( * did, substs) ;
451
+
452
+ let casting = if expected. is_ref ( ) {
453
+ format ! ( "&({fn_name} as {found_sig})" )
454
+ } else {
455
+ format ! ( "{fn_name} as {found_sig}" )
456
+ } ;
457
+
458
+ diag. help ( & format ! ( "consider casting the fn item to a fn pointer: `{}`" , casting) ) ;
423
459
}
424
460
_ => {
425
461
return ;
0 commit comments