@@ -13,7 +13,7 @@ use rustc_hir::{ExprKind, HirId, Node, QPath};
13
13
use rustc_hir_analysis:: check:: intrinsicck:: InlineAsmCtxt ;
14
14
use rustc_hir_analysis:: check:: potentially_plural_count;
15
15
use rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ;
16
- use rustc_index:: IndexVec ;
16
+ use rustc_index:: { Idx , IndexVec } ;
17
17
use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk , TypeTrace } ;
18
18
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
19
19
use rustc_middle:: ty:: error:: TypeError ;
@@ -2374,22 +2374,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2374
2374
2375
2375
let check_for_matched_generics = || {
2376
2376
if matched_inputs. iter ( ) . any ( |x| x. is_some ( ) )
2377
- && params_with_generics. iter ( ) . any ( |x | x. 1 . is_some ( ) )
2377
+ && params_with_generics. iter ( ) . any ( |( x , _ ) | x. is_some ( ) )
2378
2378
{
2379
- for & ( idx, generic, _) in & params_with_generics {
2379
+ for ( idx, ( generic, _) ) in params_with_generics. iter_enumerated ( ) {
2380
2380
// Param has to have a generic and be matched to be relevant
2381
- if matched_inputs[ idx. into ( ) ] . is_none ( ) {
2381
+ if matched_inputs[ idx] . is_none ( ) {
2382
2382
continue ;
2383
2383
}
2384
2384
2385
2385
let Some ( generic) = generic else {
2386
2386
continue ;
2387
2387
} ;
2388
2388
2389
- for unmatching_idx in idx + 1 ..params_with_generics. len ( ) {
2390
- if matched_inputs[ unmatching_idx. into ( ) ] . is_none ( )
2389
+ for unmatching_idx in
2390
+ idx. plus ( 1 ) ..ExpectedIdx :: from_usize ( params_with_generics. len ( ) )
2391
+ {
2392
+ if matched_inputs[ unmatching_idx] . is_none ( )
2391
2393
&& let Some ( unmatched_idx_param_generic) =
2392
- params_with_generics[ unmatching_idx] . 1
2394
+ params_with_generics[ unmatching_idx] . 0
2393
2395
&& unmatched_idx_param_generic. name . ident ( )
2394
2396
== generic. name . ident ( )
2395
2397
{
@@ -2404,40 +2406,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2404
2406
2405
2407
let check_for_matched_generics = check_for_matched_generics ( ) ;
2406
2408
2407
- for & ( idx, generic_param, param) in
2408
- params_with_generics. iter ( ) . filter ( |& ( idx, _ , _) | {
2409
+ for ( idx, & ( generic_param, param) ) in
2410
+ params_with_generics. iter_enumerated ( ) . filter ( |& ( idx, _) | {
2409
2411
check_for_matched_generics
2410
- || expected_idx. is_none_or ( |expected_idx| expected_idx == * idx)
2412
+ || expected_idx
2413
+ . is_none_or ( |expected_idx| expected_idx == idx. as_usize ( ) )
2411
2414
} )
2412
2415
{
2413
2416
let Some ( generic_param) = generic_param else {
2414
2417
spans. push_span_label ( param. span , "" ) ;
2415
2418
continue ;
2416
2419
} ;
2417
2420
2418
- let other_params_matched: Vec < ( usize , & hir:: Param < ' _ > ) > = params_with_generics
2419
- . iter ( )
2420
- . filter ( |( other_idx, other_generic_param, _) | {
2421
- if * other_idx == idx {
2422
- return false ;
2423
- }
2424
- let Some ( other_generic_param) = other_generic_param else {
2425
- return false ;
2426
- } ;
2427
- if matched_inputs[ idx. into ( ) ] . is_none ( )
2428
- && matched_inputs[ ( * other_idx) . into ( ) ] . is_none ( )
2429
- {
2430
- return false ;
2431
- }
2432
- if matched_inputs[ idx. into ( ) ] . is_some ( )
2433
- && matched_inputs[ ( * other_idx) . into ( ) ] . is_some ( )
2434
- {
2435
- return false ;
2436
- }
2437
- other_generic_param. name . ident ( ) == generic_param. name . ident ( )
2438
- } )
2439
- . map ( |& ( other_idx, _, other_param) | ( other_idx, other_param) )
2440
- . collect ( ) ;
2421
+ let other_params_matched: Vec < ( ExpectedIdx , & hir:: Param < ' _ > ) > =
2422
+ params_with_generics
2423
+ . iter_enumerated ( )
2424
+ . filter ( |& ( other_idx, & ( other_generic_param, _) ) | {
2425
+ if other_idx == idx {
2426
+ return false ;
2427
+ }
2428
+ let Some ( other_generic_param) = other_generic_param else {
2429
+ return false ;
2430
+ } ;
2431
+ if matched_inputs[ idx] . is_none ( )
2432
+ && matched_inputs[ other_idx] . is_none ( )
2433
+ {
2434
+ return false ;
2435
+ }
2436
+ if matched_inputs[ idx] . is_some ( )
2437
+ && matched_inputs[ other_idx] . is_some ( )
2438
+ {
2439
+ return false ;
2440
+ }
2441
+ other_generic_param. name . ident ( ) == generic_param. name . ident ( )
2442
+ } )
2443
+ . map ( |( other_idx, & ( _, other_param) ) | ( other_idx, other_param) )
2444
+ . collect ( ) ;
2441
2445
2442
2446
if !other_params_matched. is_empty ( ) {
2443
2447
let other_param_matched_names: Vec < String > = other_params_matched
@@ -2447,16 +2451,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2447
2451
{
2448
2452
format ! ( "`{ident}`" )
2449
2453
} else {
2450
- format ! ( "parameter #{}" , idx + 1 )
2454
+ format ! ( "parameter #{}" , idx. as_u32 ( ) + 1 )
2451
2455
}
2452
2456
} )
2453
2457
. collect ( ) ;
2454
2458
2455
2459
let matched_ty = self
2456
- . resolve_vars_if_possible ( formal_and_expected_inputs[ idx. into ( ) ] . 1 )
2460
+ . resolve_vars_if_possible ( formal_and_expected_inputs[ idx] . 1 )
2457
2461
. sort_string ( self . tcx ) ;
2458
2462
2459
- if matched_inputs[ idx. into ( ) ] . is_some ( ) {
2463
+ if matched_inputs[ idx] . is_some ( ) {
2460
2464
spans. push_span_label (
2461
2465
param. span ,
2462
2466
format ! (
@@ -2502,19 +2506,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2502
2506
} )
2503
2507
{
2504
2508
let param_idents_matching: Vec < String > = params_with_generics
2505
- . iter ( )
2506
- . filter ( |( _, generic, _) | {
2509
+ . iter_enumerated ( )
2510
+ . filter ( |& ( _, & ( generic, _) ) | {
2507
2511
if let Some ( generic) = generic {
2508
2512
generic. name . ident ( ) == generic_param. name . ident ( )
2509
2513
} else {
2510
2514
false
2511
2515
}
2512
2516
} )
2513
- . map ( |( idx, _, param) | {
2517
+ . map ( |( idx, & ( _, param) ) | {
2514
2518
if let hir:: PatKind :: Binding ( _, _, ident, _) = param. pat . kind {
2515
2519
format ! ( "`{ident}`" )
2516
2520
} else {
2517
- format ! ( "parameter #{}" , idx + 1 )
2521
+ format ! ( "parameter #{}" , idx. as_u32 ( ) + 1 )
2518
2522
}
2519
2523
} )
2520
2524
. collect ( ) ;
@@ -2607,45 +2611,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2607
2611
2608
2612
if let Some ( params_with_generics) = self . get_hir_params_with_generics ( def_id, is_method) {
2609
2613
debug_assert_eq ! ( params_with_generics. len( ) , matched_inputs. len( ) ) ;
2610
- for & ( idx, generic_param, _) in & params_with_generics {
2611
- if matched_inputs[ idx. into ( ) ] . is_none ( ) {
2614
+ for ( idx, ( generic_param, _) ) in params_with_generics. iter_enumerated ( ) {
2615
+ if matched_inputs[ idx] . is_none ( ) {
2612
2616
continue ;
2613
2617
}
2614
2618
2615
- let Some ( ( _, matched_arg_span) ) = provided_arg_tys. get ( idx. into ( ) ) else {
2619
+ let Some ( ( _, matched_arg_span) ) = provided_arg_tys. get ( idx. to_provided_idx ( ) )
2620
+ else {
2616
2621
continue ;
2617
2622
} ;
2618
2623
2619
2624
let Some ( generic_param) = generic_param else {
2620
2625
continue ;
2621
2626
} ;
2622
2627
2623
- let mut idxs_matched: Vec < usize > = vec ! [ ] ;
2624
- for & ( other_idx , _ , _ ) in
2625
- params_with_generics . iter ( ) . filter ( |& & ( other_idx, other_generic_param, _) | {
2628
+ let idxs_matched = params_with_generics
2629
+ . iter_enumerated ( )
2630
+ . filter ( |& ( other_idx, ( other_generic_param, _) ) | {
2626
2631
if other_idx == idx {
2627
2632
return false ;
2628
2633
}
2629
2634
let Some ( other_generic_param) = other_generic_param else {
2630
2635
return false ;
2631
2636
} ;
2632
- if matched_inputs[ other_idx. into ( ) ] . is_some ( ) {
2637
+ if matched_inputs[ other_idx] . is_some ( ) {
2633
2638
return false ;
2634
2639
}
2635
2640
other_generic_param. name . ident ( ) == generic_param. name . ident ( )
2636
2641
} )
2637
- {
2638
- idxs_matched. push ( other_idx) ;
2639
- }
2642
+ . count ( ) ;
2640
2643
2641
- if idxs_matched. is_empty ( ) {
2644
+ if idxs_matched == 0 {
2642
2645
continue ;
2643
2646
}
2644
2647
2645
2648
let expected_display_type = self
2646
2649
. resolve_vars_if_possible ( formal_and_expected_inputs[ idx. into ( ) ] . 1 )
2647
2650
. sort_string ( self . tcx ) ;
2648
- let label = if idxs_matched. len ( ) == params_with_generics. len ( ) - 1 {
2651
+ let label = if idxs_matched == params_with_generics. len ( ) - 1 {
2649
2652
format ! (
2650
2653
"expected all arguments to be this {} type because they need to match the type of this parameter" ,
2651
2654
expected_display_type
@@ -2664,60 +2667,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2664
2667
}
2665
2668
2666
2669
/// Returns the parameters of a function, with their generic parameters if those are the full
2667
- /// type of that parameter. Returns `None` if the function body is unavailable (eg is an instrinsic).
2670
+ /// type of that parameter. Returns `None` if the function has no generics or the body is
2671
+ /// unavailable (eg is an instrinsic).
2668
2672
fn get_hir_params_with_generics (
2669
2673
& self ,
2670
2674
def_id : DefId ,
2671
2675
is_method : bool ,
2672
- ) -> Option < Vec < ( usize , Option < & hir:: GenericParam < ' _ > > , & hir:: Param < ' _ > ) > > {
2676
+ ) -> Option < IndexVec < ExpectedIdx , ( Option < & hir:: GenericParam < ' _ > > , & hir:: Param < ' _ > ) > > {
2673
2677
let fn_node = self . tcx . hir ( ) . get_if_local ( def_id) ?;
2674
2678
let fn_decl = fn_node. fn_decl ( ) ?;
2679
+ let generic_params = fn_node. generics ( ) ?. params ;
2675
2680
2676
- let generic_params: Vec < Option < & hir:: GenericParam < ' _ > > > = fn_decl
2677
- . inputs
2678
- . into_iter ( )
2679
- . skip ( if is_method { 1 } else { 0 } )
2680
- . map ( |param| {
2681
- if let hir:: TyKind :: Path ( QPath :: Resolved (
2682
- _,
2683
- hir:: Path { res : Res :: Def ( _, res_def_id) , .. } ,
2684
- ) ) = param. kind
2685
- {
2686
- fn_node
2687
- . generics ( )
2688
- . into_iter ( )
2689
- . flat_map ( |generics| generics. params )
2690
- . find ( |param| & param. def_id . to_def_id ( ) == res_def_id)
2691
- } else {
2692
- None
2693
- }
2694
- } )
2695
- . collect ( ) ;
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( ) ) ;
2696
2687
2697
- let mut params: Vec < & hir:: Param < ' _ > > = self
2698
- . tcx
2699
- . hir ( )
2700
- . body ( fn_node. body_id ( ) ?)
2701
- . params
2702
- . into_iter ( )
2703
- . skip ( if is_method { 1 } else { 0 } )
2704
- . collect ( ) ;
2705
-
2706
- // The surrounding code expects variadic functions to not have a parameter representing
2707
- // the "..." parameter. This is already true of the FnDecl but not of the body params, so
2708
- // we drop it if it exists.
2709
-
2710
- if fn_decl. c_variadic {
2711
- params. pop ( ) ;
2712
- }
2713
-
2714
- debug_assert_eq ! ( params. len( ) , generic_params. len( ) ) ;
2715
2688
Some (
2716
- generic_params
2689
+ fn_inputs
2717
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
+ } )
2718
2702
. zip ( params)
2719
- . enumerate ( )
2720
- . map ( |( a, ( b, c) ) | ( a, b, c) )
2721
2703
. collect ( ) ,
2722
2704
)
2723
2705
}
0 commit comments