@@ -380,7 +380,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
380380 return ;
381381 }
382382
383- let ( msg, sugg ) = match ( expected. is_ref ( ) , found. is_ref ( ) ) {
383+ let ( msg, sug ) = match ( expected. is_ref ( ) , found. is_ref ( ) ) {
384384 ( true , false ) => {
385385 let msg = "consider using a reference" ;
386386 let sug = format ! ( "&{fn_name}" ) ;
@@ -404,22 +404,58 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
404404 ( msg, sug)
405405 }
406406 } ;
407- diag. span_suggestion ( span, msg, & sugg , Applicability :: MaybeIncorrect ) ;
407+ diag. span_suggestion ( span, msg, sug , Applicability :: MaybeIncorrect ) ;
408408 }
409409 ( ty:: FnDef ( did1, substs1) , ty:: FnDef ( did2, substs2) ) => {
410410 let expected_sig =
411411 & ( self . normalize_fn_sig ) ( self . tcx . bound_fn_sig ( * did1) . subst ( self . tcx , substs1) ) ;
412412 let found_sig =
413413 & ( self . normalize_fn_sig ) ( self . tcx . bound_fn_sig ( * did2) . subst ( self . tcx , substs2) ) ;
414414
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 ;
419426 }
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 ) ;
420440 }
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) ) ;
423459 }
424460 _ => {
425461 return ;
0 commit comments