@@ -21,7 +21,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
21
21
use rustc_middle:: ty:: { self , IsSuggestable , Ty , TyCtxt } ;
22
22
use rustc_middle:: { bug, span_bug} ;
23
23
use rustc_session:: Session ;
24
- use rustc_span:: { DUMMY_SP , Ident , Span , kw, sym} ;
24
+ use rustc_span:: { DUMMY_SP , Ident , Span , Symbol , kw, sym} ;
25
25
use rustc_trait_selection:: error_reporting:: infer:: { FailureCode , ObligationCauseExt } ;
26
26
use rustc_trait_selection:: infer:: InferCtxtExt ;
27
27
use rustc_trait_selection:: traits:: { self , ObligationCauseCode , ObligationCtxt , SelectionContext } ;
@@ -2414,11 +2414,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2414
2414
} )
2415
2415
{
2416
2416
let Some ( generic_param) = generic_param else {
2417
- spans. push_span_label ( param. span , "" ) ;
2417
+ spans. push_span_label ( param. span ( ) , "" ) ;
2418
2418
continue ;
2419
2419
} ;
2420
2420
2421
- let other_params_matched: Vec < ( ExpectedIdx , & hir :: Param < ' _ > ) > =
2421
+ let other_params_matched: Vec < ( ExpectedIdx , FnParam < ' _ > ) > =
2422
2422
params_with_generics
2423
2423
. iter_enumerated ( )
2424
2424
. filter ( |& ( other_idx, & ( other_generic_param, _) ) | {
@@ -2447,9 +2447,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2447
2447
let other_param_matched_names: Vec < String > = other_params_matched
2448
2448
. iter ( )
2449
2449
. map ( |( idx, other_param) | {
2450
- if let hir:: PatKind :: Binding ( _, _, ident, _) = other_param. pat . kind
2451
- {
2452
- format ! ( "`{ident}`" )
2450
+ if let Some ( name) = other_param. name ( ) {
2451
+ format ! ( "`{name}`" )
2453
2452
} else {
2454
2453
format ! ( "parameter #{}" , idx. as_u32( ) + 1 )
2455
2454
}
@@ -2462,7 +2461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2462
2461
2463
2462
if matched_inputs[ idx] . is_some ( ) {
2464
2463
spans. push_span_label (
2465
- param. span ,
2464
+ param. span ( ) ,
2466
2465
format ! (
2467
2466
"{} need{} to match the {} type of this parameter" ,
2468
2467
listify( & other_param_matched_names, |n| n. to_string( ) )
@@ -2477,7 +2476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2477
2476
) ;
2478
2477
} else {
2479
2478
spans. push_span_label (
2480
- param. span ,
2479
+ param. span ( ) ,
2481
2480
format ! (
2482
2481
"this parameter needs to match the {} type of {}" ,
2483
2482
matched_ty,
@@ -2488,7 +2487,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2488
2487
}
2489
2488
generics_with_unmatched_params. push ( generic_param) ;
2490
2489
} else {
2491
- spans. push_span_label ( param. span , "" ) ;
2490
+ spans. push_span_label ( param. span ( ) , "" ) ;
2492
2491
}
2493
2492
}
2494
2493
@@ -2515,8 +2514,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2515
2514
}
2516
2515
} )
2517
2516
. map ( |( idx, & ( _, param) ) | {
2518
- if let hir :: PatKind :: Binding ( _ , _ , ident , _ ) = param. pat . kind {
2519
- format ! ( "`{ident }`" )
2517
+ if let Some ( name ) = param. name ( ) {
2518
+ format ! ( "`{name }`" )
2520
2519
} else {
2521
2520
format ! ( "parameter #{}" , idx. as_u32( ) + 1 )
2522
2521
}
@@ -2673,35 +2672,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2673
2672
& self ,
2674
2673
def_id : DefId ,
2675
2674
is_method : bool ,
2676
- ) -> Option < IndexVec < ExpectedIdx , ( Option < & hir:: GenericParam < ' _ > > , & hir:: Param < ' _ > ) > > {
2677
- let fn_node = self . tcx . hir ( ) . get_if_local ( def_id) ?;
2678
- let fn_decl = fn_node. fn_decl ( ) ?;
2679
- let generic_params = fn_node. generics ( ) ?. params ;
2680
-
2681
- // Remove both the receiver and variadic arguments. Neither can have an unmatched generic
2682
- // parameter.
2683
- let params = self . tcx . hir ( ) . body ( fn_node. body_id ( ) ?) . params ;
2684
- let params = params. get ( is_method as usize ..params. len ( ) - fn_decl. c_variadic as usize ) ?;
2685
- let fn_inputs = fn_decl. inputs . get ( is_method as usize ..) ?;
2686
- debug_assert_eq ! ( params. len( ) , fn_inputs. len( ) ) ;
2687
-
2688
- Some (
2689
- fn_inputs
2690
- . into_iter ( )
2691
- . map ( |param| {
2692
- if let hir:: TyKind :: Path ( QPath :: Resolved (
2693
- _,
2694
- & hir:: Path { res : Res :: Def ( _, res_def_id) , .. } ,
2695
- ) ) = param. kind
2696
- {
2697
- generic_params. iter ( ) . find ( |param| param. def_id . to_def_id ( ) == res_def_id)
2698
- } else {
2699
- None
2700
- }
2701
- } )
2702
- . zip ( params)
2703
- . collect ( ) ,
2704
- )
2675
+ ) -> Option < IndexVec < ExpectedIdx , ( Option < & hir:: GenericParam < ' _ > > , FnParam < ' _ > ) > > {
2676
+ let ( sig, generics, body_id, param_names) = match self . tcx . hir ( ) . get_if_local ( def_id) ? {
2677
+ hir:: Node :: TraitItem ( & hir:: TraitItem {
2678
+ generics,
2679
+ kind : hir:: TraitItemKind :: Fn ( sig, trait_fn) ,
2680
+ ..
2681
+ } ) => match trait_fn {
2682
+ hir:: TraitFn :: Required ( params) => ( sig, generics, None , Some ( params) ) ,
2683
+ hir:: TraitFn :: Provided ( body) => ( sig, generics, Some ( body) , None ) ,
2684
+ } ,
2685
+ hir:: Node :: ImplItem ( & hir:: ImplItem {
2686
+ generics,
2687
+ kind : hir:: ImplItemKind :: Fn ( sig, body) ,
2688
+ ..
2689
+ } )
2690
+ | hir:: Node :: Item ( & hir:: Item {
2691
+ kind : hir:: ItemKind :: Fn { sig, generics, body, .. } ,
2692
+ ..
2693
+ } ) => ( sig, generics, Some ( body) , None ) ,
2694
+ _ => return None ,
2695
+ } ;
2696
+
2697
+ // Make sure to remove both the receiver and variadic argument. Both are removed
2698
+ // when matching parameter types.
2699
+ let fn_inputs = sig. decl . inputs . get ( is_method as usize ..) ?. iter ( ) . map ( |param| {
2700
+ if let hir:: TyKind :: Path ( QPath :: Resolved (
2701
+ _,
2702
+ & hir:: Path { res : Res :: Def ( _, res_def_id) , .. } ,
2703
+ ) ) = param. kind
2704
+ {
2705
+ generics. params . iter ( ) . find ( |param| param. def_id . to_def_id ( ) == res_def_id)
2706
+ } else {
2707
+ None
2708
+ }
2709
+ } ) ;
2710
+ match ( body_id, param_names) {
2711
+ ( Some ( _) , Some ( _) ) | ( None , None ) => unreachable ! ( ) ,
2712
+ ( Some ( body) , None ) => {
2713
+ let params = self . tcx . hir ( ) . body ( body) . params ;
2714
+ let params =
2715
+ params. get ( is_method as usize ..params. len ( ) - sig. decl . c_variadic as usize ) ?;
2716
+ debug_assert_eq ! ( params. len( ) , fn_inputs. len( ) ) ;
2717
+ Some ( fn_inputs. zip ( params. iter ( ) . map ( |param| FnParam :: Param ( param) ) ) . collect ( ) )
2718
+ }
2719
+ ( None , Some ( params) ) => {
2720
+ let params = params. get ( is_method as usize ..) ?;
2721
+ debug_assert_eq ! ( params. len( ) , fn_inputs. len( ) ) ;
2722
+ Some ( fn_inputs. zip ( params. iter ( ) . map ( |param| FnParam :: Name ( param) ) ) . collect ( ) )
2723
+ }
2724
+ }
2705
2725
}
2706
2726
}
2707
2727
@@ -2724,3 +2744,27 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2724
2744
hir:: intravisit:: walk_expr ( self , ex) ;
2725
2745
}
2726
2746
}
2747
+
2748
+ #[ derive( Clone , Copy ) ]
2749
+ enum FnParam < ' hir > {
2750
+ Param ( & ' hir hir:: Param < ' hir > ) ,
2751
+ Name ( & ' hir Ident ) ,
2752
+ }
2753
+ impl FnParam < ' _ > {
2754
+ fn span ( & self ) -> Span {
2755
+ match self {
2756
+ Self :: Param ( x) => x. span ,
2757
+ Self :: Name ( x) => x. span ,
2758
+ }
2759
+ }
2760
+
2761
+ fn name ( & self ) -> Option < Symbol > {
2762
+ match self {
2763
+ Self :: Param ( x) if let hir:: PatKind :: Binding ( _, _, ident, _) = x. pat . kind => {
2764
+ Some ( ident. name )
2765
+ }
2766
+ Self :: Name ( x) if x. name != kw:: Empty => Some ( x. name ) ,
2767
+ _ => None ,
2768
+ }
2769
+ }
2770
+ }
0 commit comments