@@ -13,7 +13,7 @@ use rustc_hir::{ExprKind, HirId, Node, QPath};
1313use rustc_hir_analysis:: check:: intrinsicck:: InlineAsmCtxt ;
1414use rustc_hir_analysis:: check:: potentially_plural_count;
1515use rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ;
16- use rustc_index:: IndexVec ;
16+ use rustc_index:: { Idx , IndexVec } ;
1717use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk , TypeTrace } ;
1818use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
1919use rustc_middle:: ty:: error:: TypeError ;
@@ -2374,22 +2374,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23742374
23752375 let check_for_matched_generics = || {
23762376 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 ( ) )
23782378 {
2379- for & ( idx, generic, _) in & params_with_generics {
2379+ for ( idx, ( generic, _) ) in params_with_generics. iter_enumerated ( ) {
23802380 // 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 ( ) {
23822382 continue ;
23832383 }
23842384
23852385 let Some ( generic) = generic else {
23862386 continue ;
23872387 } ;
23882388
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 ( )
23912393 && let Some ( unmatched_idx_param_generic) =
2392- params_with_generics[ unmatching_idx] . 1
2394+ params_with_generics[ unmatching_idx] . 0
23932395 && unmatched_idx_param_generic. name . ident ( )
23942396 == generic. name . ident ( )
23952397 {
@@ -2404,40 +2406,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24042406
24052407 let check_for_matched_generics = check_for_matched_generics ( ) ;
24062408
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, _) | {
24092411 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 ( ) )
24112414 } )
24122415 {
24132416 let Some ( generic_param) = generic_param else {
24142417 spans. push_span_label ( param. span , "" ) ;
24152418 continue ;
24162419 } ;
24172420
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 ( ) ;
24412445
24422446 if !other_params_matched. is_empty ( ) {
24432447 let other_param_matched_names: Vec < String > = other_params_matched
@@ -2447,16 +2451,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24472451 {
24482452 format ! ( "`{ident}`" )
24492453 } else {
2450- format ! ( "parameter #{}" , idx + 1 )
2454+ format ! ( "parameter #{}" , idx. as_u32 ( ) + 1 )
24512455 }
24522456 } )
24532457 . collect ( ) ;
24542458
24552459 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 )
24572461 . sort_string ( self . tcx ) ;
24582462
2459- if matched_inputs[ idx. into ( ) ] . is_some ( ) {
2463+ if matched_inputs[ idx] . is_some ( ) {
24602464 spans. push_span_label (
24612465 param. span ,
24622466 format ! (
@@ -2502,19 +2506,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25022506 } )
25032507 {
25042508 let param_idents_matching: Vec < String > = params_with_generics
2505- . iter ( )
2506- . filter ( |( _, generic, _) | {
2509+ . iter_enumerated ( )
2510+ . filter ( |& ( _, & ( generic, _) ) | {
25072511 if let Some ( generic) = generic {
25082512 generic. name . ident ( ) == generic_param. name . ident ( )
25092513 } else {
25102514 false
25112515 }
25122516 } )
2513- . map ( |( idx, _, param) | {
2517+ . map ( |( idx, & ( _, param) ) | {
25142518 if let hir:: PatKind :: Binding ( _, _, ident, _) = param. pat . kind {
25152519 format ! ( "`{ident}`" )
25162520 } else {
2517- format ! ( "parameter #{}" , idx + 1 )
2521+ format ! ( "parameter #{}" , idx. as_u32 ( ) + 1 )
25182522 }
25192523 } )
25202524 . collect ( ) ;
@@ -2607,45 +2611,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26072611
26082612 if let Some ( params_with_generics) = self . get_hir_params_with_generics ( def_id, is_method) {
26092613 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 ( ) {
26122616 continue ;
26132617 }
26142618
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 {
26162621 continue ;
26172622 } ;
26182623
26192624 let Some ( generic_param) = generic_param else {
26202625 continue ;
26212626 } ;
26222627
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, _) ) | {
26262631 if other_idx == idx {
26272632 return false ;
26282633 }
26292634 let Some ( other_generic_param) = other_generic_param else {
26302635 return false ;
26312636 } ;
2632- if matched_inputs[ other_idx. into ( ) ] . is_some ( ) {
2637+ if matched_inputs[ other_idx] . is_some ( ) {
26332638 return false ;
26342639 }
26352640 other_generic_param. name . ident ( ) == generic_param. name . ident ( )
26362641 } )
2637- {
2638- idxs_matched. push ( other_idx) ;
2639- }
2642+ . count ( ) ;
26402643
2641- if idxs_matched. is_empty ( ) {
2644+ if idxs_matched == 0 {
26422645 continue ;
26432646 }
26442647
26452648 let expected_display_type = self
26462649 . resolve_vars_if_possible ( formal_and_expected_inputs[ idx. into ( ) ] . 1 )
26472650 . 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 {
26492652 format ! (
26502653 "expected all arguments to be this {} type because they need to match the type of this parameter" ,
26512654 expected_display_type
@@ -2664,60 +2667,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26642667 }
26652668
26662669 /// 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).
26682672 fn get_hir_params_with_generics (
26692673 & self ,
26702674 def_id : DefId ,
26712675 is_method : bool ,
2672- ) -> Option < Vec < ( usize , Option < & hir:: GenericParam < ' _ > > , & hir:: Param < ' _ > ) > > {
2676+ ) -> Option < IndexVec < ExpectedIdx , ( Option < & hir:: GenericParam < ' _ > > , & hir:: Param < ' _ > ) > > {
26732677 let fn_node = self . tcx . hir ( ) . get_if_local ( def_id) ?;
26742678 let fn_decl = fn_node. fn_decl ( ) ?;
2679+ let generic_params = fn_node. generics ( ) ?. params ;
26752680
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( ) ) ;
26962687
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( ) ) ;
27152688 Some (
2716- generic_params
2689+ fn_inputs
27172690 . 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+ } )
27182702 . zip ( params)
2719- . enumerate ( )
2720- . map ( |( a, ( b, c) ) | ( a, b, c) )
27212703 . collect ( ) ,
27222704 )
27232705 }
0 commit comments