@@ -18,7 +18,7 @@ use rustc_ast as ast;
1818use rustc_data_structures:: fx:: FxIndexSet ;
1919use rustc_errors:: {
2020 a_or_an, codes:: * , display_list_with_comma_and, pluralize, Applicability , Diag ,
21- DiagnosticBuilder , ErrorGuaranteed , MultiSpan , StashKey ,
21+ ErrorGuaranteed , MultiSpan , StashKey ,
2222} ;
2323use rustc_hir as hir;
2424use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
@@ -2202,81 +2202,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22022202 {
22032203 let mut spans: MultiSpan = def_span. into ( ) ;
22042204
2205- let param_generics: Vec < Option < & hir:: GenericParam < ' _ > > > = self
2206- . tcx
2207- . hir ( )
2208- . get_if_local ( def_id)
2209- . and_then ( |node| node. fn_decl ( ) )
2210- . into_iter ( )
2211- . flat_map ( |decl| decl. inputs )
2212- . skip ( if is_method { 1 } else { 0 } )
2213- . map ( |param| {
2214- if let hir:: TyKind :: Path ( QPath :: Resolved (
2215- _,
2216- hir:: Path { res : Res :: Def ( _, res_def_id) , .. } ,
2217- ) ) = param. kind
2218- {
2219- self . tcx
2220- . hir ( )
2221- . get_if_local ( def_id)
2222- . and_then ( |node| node. generics ( ) )
2223- . into_iter ( )
2224- . flat_map ( |generics| generics. params )
2225- . find ( |gen| & gen. def_id . to_def_id ( ) == res_def_id)
2226- } else {
2227- None
2228- }
2229- } )
2230- . collect ( ) ;
2205+ let params_with_generics = self . get_hir_params_with_generics ( def_id, is_method) ;
22312206
2232- let params: Vec < & hir:: Param < ' _ > > = self
2233- . tcx
2234- . hir ( )
2235- . get_if_local ( def_id)
2236- . and_then ( |node| node. body_id ( ) )
2237- . into_iter ( )
2238- . flat_map ( |id| self . tcx . hir ( ) . body ( id) . params )
2239- . skip ( if is_method { 1 } else { 0 } )
2240- . collect ( ) ;
2241-
2242- let check_for_matched_generics_fn = || {
2243- if params. len ( ) == param_generics. len ( )
2244- && matched_inputs. iter ( ) . any ( |x| x. is_some ( ) )
2245- && param_generics. iter ( ) . any ( |x| x. is_some ( ) )
2246- {
2247- for ( idx, generic) in param_generics. iter ( ) . enumerate ( ) {
2248- if matched_inputs[ idx. into ( ) ] . is_none ( ) {
2249- continue ;
2250- }
2207+ let mut check_for_matched_generics = false ;
2208+ if matched_inputs. iter ( ) . any ( |x| x. is_some ( ) )
2209+ && params_with_generics. iter ( ) . any ( |x| x. 0 . is_some ( ) )
2210+ {
2211+ for ( idx, ( generic, _) ) in params_with_generics. iter ( ) . enumerate ( ) {
2212+ // Param has to have a generic and be matched to be relevant
2213+ if matched_inputs[ idx. into ( ) ] . is_none ( ) {
2214+ continue ;
2215+ }
22512216
2252- let Some ( generic) = generic else {
2253- continue ;
2254- } ;
2217+ let Some ( generic) = generic else {
2218+ continue ;
2219+ } ;
22552220
2256- for unmatching_idx in idx + 1 ..params . len ( ) {
2257- if matched_inputs[ unmatching_idx. into ( ) ] . is_none ( )
2258- && let Some ( unmatched_idx_param_generic) =
2259- param_generics [ unmatching_idx]
2260- && unmatched_idx_param_generic. name . ident ( ) == generic. name . ident ( )
2261- {
2262- return true ;
2263- }
2221+ for unmatching_idx in idx + 1 ..params_with_generics . len ( ) {
2222+ if matched_inputs[ unmatching_idx. into ( ) ] . is_none ( )
2223+ && let Some ( unmatched_idx_param_generic) =
2224+ params_with_generics [ unmatching_idx] . 0
2225+ && unmatched_idx_param_generic. name . ident ( ) == generic. name . ident ( )
2226+ {
2227+ // We found a parameter that didn't match that needed to
2228+ check_for_matched_generics = true ;
22642229 }
22652230 }
22662231 }
2267- false
2268- } ;
2232+ }
22692233
2270- if check_for_matched_generics_fn ( ) {
2234+ if check_for_matched_generics {
22712235 let mut generics_map: Vec < ( usize , & hir:: GenericParam < ' _ > ) > = Vec :: new ( ) ;
22722236 // This is a map from the index of the generic to the index of the parameter and the
22732237 // parameter
22742238 let mut matched_params_map: Vec < ( usize , usize , & hir:: Param < ' _ > ) > = Vec :: new ( ) ;
22752239 let mut unmatched_params_map: Vec < ( usize , & hir:: Param < ' _ > ) > = Vec :: new ( ) ;
22762240
2277- for ( idx, ( param, generic) ) in
2278- params. iter ( ) . zip_eq ( param_generics. iter ( ) ) . enumerate ( )
2279- {
2241+ for ( idx, ( generic, param) ) in params_with_generics. iter ( ) . enumerate ( ) {
22802242 if matched_inputs[ idx. into ( ) ] . is_none ( ) {
22812243 spans. push_span_label ( param. span , "" ) ;
22822244 continue ;
@@ -2289,13 +2251,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22892251
22902252 let mut found_unmatched_generic_params = vec ! [ ] ;
22912253
2292- for unmatching_idx in idx + 1 ..params . len ( ) {
2254+ for unmatching_idx in idx + 1 ..params_with_generics . len ( ) {
22932255 if matched_inputs[ unmatching_idx. into ( ) ] . is_none ( )
22942256 && let Some ( unmatched_idx_param_generic) =
2295- param_generics [ unmatching_idx]
2257+ params_with_generics [ unmatching_idx] . 0
22962258 && unmatched_idx_param_generic. name . ident ( ) == generic. name . ident ( )
22972259 {
2298- found_unmatched_generic_params. push ( params[ unmatching_idx] ) ;
2260+ found_unmatched_generic_params
2261+ . push ( params_with_generics[ unmatching_idx] . 1 ) ;
22992262 }
23002263 }
23012264
@@ -2398,7 +2361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23982361 }
23992362 }
24002363
2401- for matched_param in & matched_params {
2364+ for ( idx , matched_param) in matched_params. iter ( ) . enumerate ( ) {
24022365 let idents: Vec < String > = unmatched_params
24032366 . iter ( )
24042367 . map ( |x| {
@@ -2410,17 +2373,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24102373 } )
24112374 . collect ( ) ;
24122375
2376+ let matched_ty = self
2377+ . resolve_vars_if_possible ( formal_and_expected_inputs[ idx. into ( ) ] . 0 )
2378+ . sort_string ( self . tcx ) ;
2379+
24132380 spans. push_span_label (
24142381 matched_param. 1 . span ,
24152382 format ! (
2416- "{} needs to match the type of this parameter" ,
2417- display_list_with_comma_and( & idents)
2383+ "{} {} to match the {} type of this parameter" ,
2384+ display_list_with_comma_and( & idents) ,
2385+ format!(
2386+ "need{}" ,
2387+ pluralize!( if idents. len( ) == 1 { 0 } else { 1 } )
2388+ ) ,
2389+ matched_ty,
24182390 ) ,
24192391 ) ;
24202392 }
24212393 }
24222394 } else {
2423- for ( _, param) in params . iter ( ) . enumerate ( ) . filter ( |( idx, _) | {
2395+ for ( _, ( _ , param) ) in params_with_generics . iter ( ) . enumerate ( ) . filter ( |( idx, _) | {
24242396 expected_idx. map_or ( true , |expected_idx| expected_idx == * idx)
24252397 } ) {
24262398 spans. push_span_label ( param. span , "" ) ;
@@ -2491,7 +2463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24912463
24922464 fn label_generic_mismatches (
24932465 & self ,
2494- err : & mut DiagnosticBuilder < ' _ > ,
2466+ err : & mut Diag < ' _ > ,
24952467 callable_def_id : Option < DefId > ,
24962468 matched_inputs : & IndexVec < ExpectedIdx , Option < ProvidedIdx > > ,
24972469 provided_arg_tys : & IndexVec < ProvidedIdx , ( Ty < ' tcx > , Span ) > ,
@@ -2571,35 +2543,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25712543 "expected all arguments to be {} because they need to match the type of this parameter" ,
25722544 expected_display_type
25732545 )
2574- } else if all_pats_matched. len ( ) == incompatible_pats_matched. len ( ) {
2575- format ! (
2576- "expected {} {} to be {} {} because {} to match the type of this parameter" ,
2577- format!( "argument{}" , pluralize!( incompatible_pats_matched. len( ) ) ) ,
2578- display_list_with_comma_and( & incompatible_pats_matched) ,
2579- a_or_an( & expected_display_type) ,
2580- expected_display_type,
2581- if all_pats_matched. len( ) == 1 {
2582- "that argument needs"
2583- } else {
2584- "those arguments need"
2585- }
2586- )
25872546 } else {
25882547 format ! (
2589- "expected {} {} to be {} {} because the {} {} {} to match the type of this parameter" ,
2590- format!( "argument{}" , pluralize!( incompatible_pats_matched. len( ) ) ) ,
2591- display_list_with_comma_and( & incompatible_pats_matched) ,
2548+ "expected some other arguments to be {} {} to match the type of this parameter" ,
25922549 a_or_an( & expected_display_type) ,
25932550 expected_display_type,
2594- format!( "argument{}" , pluralize!( all_pats_matched. len( ) ) ) ,
2595- display_list_with_comma_and( & all_pats_matched) ,
2596- format!( "need{}" , pluralize!( if all_pats_matched. len( ) == 1 { 0 } else { 1 } ) ) ,
25972551 )
25982552 } ;
25992553
26002554 err. span_label ( matched_arg_span, label) ;
26012555 }
26022556 }
2557+
2558+ fn get_hir_params_with_generics (
2559+ & self ,
2560+ def_id : DefId ,
2561+ is_method : bool ,
2562+ ) -> Vec < ( Option < & hir:: GenericParam < ' _ > > , & hir:: Param < ' _ > ) > {
2563+ let fn_node = self . tcx . hir ( ) . get_if_local ( def_id) ;
2564+
2565+ let generic_params: Vec < Option < & hir:: GenericParam < ' _ > > > = fn_node
2566+ . and_then ( |node| node. fn_decl ( ) )
2567+ . into_iter ( )
2568+ . flat_map ( |decl| decl. inputs )
2569+ . skip ( if is_method { 1 } else { 0 } )
2570+ . map ( |param| {
2571+ if let hir:: TyKind :: Path ( QPath :: Resolved (
2572+ _,
2573+ hir:: Path { res : Res :: Def ( _, res_def_id) , .. } ,
2574+ ) ) = param. kind
2575+ {
2576+ fn_node
2577+ . and_then ( |node| node. generics ( ) )
2578+ . into_iter ( )
2579+ . flat_map ( |generics| generics. params )
2580+ . find ( |gen| & gen. def_id . to_def_id ( ) == res_def_id)
2581+ } else {
2582+ None
2583+ }
2584+ } )
2585+ . collect ( ) ;
2586+
2587+ let params: Vec < & hir:: Param < ' _ > > = fn_node
2588+ . and_then ( |node| node. body_id ( ) )
2589+ . into_iter ( )
2590+ . flat_map ( |id| self . tcx . hir ( ) . body ( id) . params )
2591+ . skip ( if is_method { 1 } else { 0 } )
2592+ . collect ( ) ;
2593+
2594+ generic_params. into_iter ( ) . zip ( params) . collect ( )
2595+ }
26032596}
26042597
26052598struct FindClosureArg < ' tcx > {
0 commit comments