@@ -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
} ;
@@ -369,14 +370,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
369
370
}
370
371
}
371
372
372
- pub ( super ) fn suggest_function_pointers (
373
+ pub fn suggest_function_pointers_impl (
373
374
& self ,
374
- cause : & ObligationCause < ' tcx > ,
375
- span : Span ,
375
+ span : Option < Span > ,
376
376
exp_found : & ty:: error:: ExpectedFound < Ty < ' tcx > > ,
377
377
diag : & mut Diag < ' _ > ,
378
378
) {
379
- debug ! ( "suggest_function_pointers(cause={:?}, exp_found={:?})" , cause, exp_found) ;
380
379
let ty:: error:: ExpectedFound { expected, found } = exp_found;
381
380
let expected_inner = expected. peel_refs ( ) ;
382
381
let found_inner = found. peel_refs ( ) ;
@@ -399,6 +398,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
399
398
return ;
400
399
}
401
400
401
+ let Some ( span) = span else {
402
+ let casting = format ! ( "{fn_name} as {sig}" ) ;
403
+ diag. subdiagnostic ( FnItemsAreDistinct ) ;
404
+ diag. subdiagnostic ( FnConsiderCasting { casting } ) ;
405
+ return ;
406
+ } ;
407
+
402
408
let sugg = match ( expected. is_ref ( ) , found. is_ref ( ) ) {
403
409
( true , false ) => FunctionPointerSuggestion :: UseRef { span, fn_name } ,
404
410
( false , true ) => FunctionPointerSuggestion :: RemoveRef { span, fn_name } ,
@@ -433,6 +439,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
433
439
}
434
440
435
441
let fn_name = self . tcx . def_path_str_with_args ( * did2, args2) ;
442
+
443
+ let Some ( span) = span else {
444
+ diag. subdiagnostic ( FnConsiderCastingBoth { sig : * expected_sig } ) ;
445
+ return ;
446
+ } ;
447
+
436
448
let sug = if found. is_ref ( ) {
437
449
FunctionPointerSuggestion :: CastBothRef {
438
450
span,
@@ -476,6 +488,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
476
488
} ;
477
489
}
478
490
491
+ pub ( super ) fn suggest_function_pointers (
492
+ & self ,
493
+ cause : & ObligationCause < ' tcx > ,
494
+ span : Span ,
495
+ exp_found : & ty:: error:: ExpectedFound < Ty < ' tcx > > ,
496
+ terr : TypeError < ' tcx > ,
497
+ diag : & mut Diag < ' _ > ,
498
+ ) {
499
+ debug ! ( "suggest_function_pointers(cause={:?}, exp_found={:?})" , cause, exp_found) ;
500
+
501
+ if exp_found. expected . peel_refs ( ) . is_fn ( ) && exp_found. found . peel_refs ( ) . is_fn ( ) {
502
+ self . suggest_function_pointers_impl ( Some ( span) , exp_found, diag) ;
503
+ } else if let TypeError :: Sorts ( exp_found) = terr {
504
+ self . suggest_function_pointers_impl ( None , & exp_found, diag) ;
505
+ }
506
+ }
507
+
479
508
pub fn should_suggest_as_ref_kind (
480
509
& self ,
481
510
expected : Ty < ' tcx > ,
0 commit comments