@@ -12,6 +12,7 @@ use rustc_middle::traits::{
12
12
IfExpressionCause , MatchExpressionArmCause , ObligationCause , ObligationCauseCode ,
13
13
StatementAsExpression ,
14
14
} ;
15
+ use rustc_middle:: ty:: error:: TypeError ;
15
16
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
16
17
use rustc_middle:: ty:: { self as ty, GenericArgKind , IsSuggestable , Ty , TypeVisitableExt } ;
17
18
use rustc_span:: { Span , sym} ;
@@ -20,7 +21,7 @@ use tracing::debug;
20
21
use crate :: error_reporting:: TypeErrCtxt ;
21
22
use crate :: error_reporting:: infer:: hir:: Path ;
22
23
use crate :: errors:: {
23
- ConsiderAddingAwait , FnConsiderCasting , FnItemsAreDistinct , FnUniqTypes ,
24
+ ConsiderAddingAwait , FnConsiderCasting , FnConsiderCastingBoth , FnItemsAreDistinct , FnUniqTypes ,
24
25
FunctionPointerSuggestion , SuggestAccessingField , SuggestRemoveSemiOrReturnBinding ,
25
26
SuggestTuplePatternMany , SuggestTuplePatternOne , TypeErrorAdditionalDiags ,
26
27
} ;
@@ -381,14 +382,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
381
382
}
382
383
}
383
384
384
- pub ( super ) fn suggest_function_pointers (
385
+ pub fn suggest_function_pointers_impl (
385
386
& self ,
386
- cause : & ObligationCause < ' tcx > ,
387
- span : Span ,
387
+ span : Option < Span > ,
388
388
exp_found : & ty:: error:: ExpectedFound < Ty < ' tcx > > ,
389
389
diag : & mut Diag < ' _ > ,
390
390
) {
391
- debug ! ( "suggest_function_pointers(cause={:?}, exp_found={:?})" , cause, exp_found) ;
392
391
let ty:: error:: ExpectedFound { expected, found } = exp_found;
393
392
let expected_inner = expected. peel_refs ( ) ;
394
393
let found_inner = found. peel_refs ( ) ;
@@ -411,6 +410,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
411
410
return ;
412
411
}
413
412
413
+ let Some ( span) = span else {
414
+ let casting = format ! ( "{fn_name} as {sig}" ) ;
415
+ diag. subdiagnostic ( FnItemsAreDistinct ) ;
416
+ diag. subdiagnostic ( FnConsiderCasting { casting } ) ;
417
+ return ;
418
+ } ;
419
+
414
420
let sugg = match ( expected. is_ref ( ) , found. is_ref ( ) ) {
415
421
( true , false ) => FunctionPointerSuggestion :: UseRef { span, fn_name } ,
416
422
( false , true ) => FunctionPointerSuggestion :: RemoveRef { span, fn_name } ,
@@ -445,6 +451,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
445
451
}
446
452
447
453
let fn_name = self . tcx . def_path_str_with_args ( * did2, args2) ;
454
+
455
+ let Some ( span) = span else {
456
+ diag. subdiagnostic ( FnConsiderCastingBoth { sig : * expected_sig } ) ;
457
+ return ;
458
+ } ;
459
+
448
460
let sug = if found. is_ref ( ) {
449
461
FunctionPointerSuggestion :: CastBothRef {
450
462
span,
@@ -488,6 +500,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
488
500
} ;
489
501
}
490
502
503
+ pub ( super ) fn suggest_function_pointers (
504
+ & self ,
505
+ cause : & ObligationCause < ' tcx > ,
506
+ span : Span ,
507
+ exp_found : & ty:: error:: ExpectedFound < Ty < ' tcx > > ,
508
+ terr : TypeError < ' tcx > ,
509
+ diag : & mut Diag < ' _ > ,
510
+ ) {
511
+ debug ! ( "suggest_function_pointers(cause={:?}, exp_found={:?})" , cause, exp_found) ;
512
+
513
+ if exp_found. expected . peel_refs ( ) . is_fn ( ) && exp_found. found . peel_refs ( ) . is_fn ( ) {
514
+ self . suggest_function_pointers_impl ( Some ( span) , exp_found, diag) ;
515
+ } else if let TypeError :: Sorts ( exp_found) = terr {
516
+ self . suggest_function_pointers_impl ( None , & exp_found, diag) ;
517
+ }
518
+ }
519
+
491
520
pub fn should_suggest_as_ref_kind (
492
521
& self ,
493
522
expected : Ty < ' tcx > ,
0 commit comments