@@ -18,7 +18,7 @@ use rustc_ast as ast;
18
18
use rustc_data_structures:: fx:: FxIndexSet ;
19
19
use rustc_errors:: {
20
20
a_or_an, codes:: * , display_list_with_comma_and, pluralize, Applicability , Diag ,
21
- DiagnosticBuilder , ErrorGuaranteed , MultiSpan , StashKey ,
21
+ ErrorGuaranteed , MultiSpan , StashKey ,
22
22
} ;
23
23
use rustc_hir as hir;
24
24
use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
@@ -2202,81 +2202,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2202
2202
{
2203
2203
let mut spans: MultiSpan = def_span. into ( ) ;
2204
2204
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) ;
2231
2206
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
+ }
2251
2216
2252
- let Some ( generic) = generic else {
2253
- continue ;
2254
- } ;
2217
+ let Some ( generic) = generic else {
2218
+ continue ;
2219
+ } ;
2255
2220
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 ;
2264
2229
}
2265
2230
}
2266
2231
}
2267
- false
2268
- } ;
2232
+ }
2269
2233
2270
- if check_for_matched_generics_fn ( ) {
2234
+ if check_for_matched_generics {
2271
2235
let mut generics_map: Vec < ( usize , & hir:: GenericParam < ' _ > ) > = Vec :: new ( ) ;
2272
2236
// This is a map from the index of the generic to the index of the parameter and the
2273
2237
// parameter
2274
2238
let mut matched_params_map: Vec < ( usize , usize , & hir:: Param < ' _ > ) > = Vec :: new ( ) ;
2275
2239
let mut unmatched_params_map: Vec < ( usize , & hir:: Param < ' _ > ) > = Vec :: new ( ) ;
2276
2240
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 ( ) {
2280
2242
if matched_inputs[ idx. into ( ) ] . is_none ( ) {
2281
2243
spans. push_span_label ( param. span , "" ) ;
2282
2244
continue ;
@@ -2289,13 +2251,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2289
2251
2290
2252
let mut found_unmatched_generic_params = vec ! [ ] ;
2291
2253
2292
- for unmatching_idx in idx + 1 ..params . len ( ) {
2254
+ for unmatching_idx in idx + 1 ..params_with_generics . len ( ) {
2293
2255
if matched_inputs[ unmatching_idx. into ( ) ] . is_none ( )
2294
2256
&& let Some ( unmatched_idx_param_generic) =
2295
- param_generics [ unmatching_idx]
2257
+ params_with_generics [ unmatching_idx] . 0
2296
2258
&& unmatched_idx_param_generic. name . ident ( ) == generic. name . ident ( )
2297
2259
{
2298
- found_unmatched_generic_params. push ( params[ unmatching_idx] ) ;
2260
+ found_unmatched_generic_params
2261
+ . push ( params_with_generics[ unmatching_idx] . 1 ) ;
2299
2262
}
2300
2263
}
2301
2264
@@ -2398,7 +2361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2398
2361
}
2399
2362
}
2400
2363
2401
- for matched_param in & matched_params {
2364
+ for ( idx , matched_param) in matched_params. iter ( ) . enumerate ( ) {
2402
2365
let idents: Vec < String > = unmatched_params
2403
2366
. iter ( )
2404
2367
. map ( |x| {
@@ -2410,17 +2373,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2410
2373
} )
2411
2374
. collect ( ) ;
2412
2375
2376
+ let matched_ty = self
2377
+ . resolve_vars_if_possible ( formal_and_expected_inputs[ idx. into ( ) ] . 0 )
2378
+ . sort_string ( self . tcx ) ;
2379
+
2413
2380
spans. push_span_label (
2414
2381
matched_param. 1 . span ,
2415
2382
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,
2418
2390
) ,
2419
2391
) ;
2420
2392
}
2421
2393
}
2422
2394
} else {
2423
- for ( _, param) in params . iter ( ) . enumerate ( ) . filter ( |( idx, _) | {
2395
+ for ( _, ( _ , param) ) in params_with_generics . iter ( ) . enumerate ( ) . filter ( |( idx, _) | {
2424
2396
expected_idx. map_or ( true , |expected_idx| expected_idx == * idx)
2425
2397
} ) {
2426
2398
spans. push_span_label ( param. span , "" ) ;
@@ -2491,7 +2463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2491
2463
2492
2464
fn label_generic_mismatches (
2493
2465
& self ,
2494
- err : & mut DiagnosticBuilder < ' _ > ,
2466
+ err : & mut Diag < ' _ > ,
2495
2467
callable_def_id : Option < DefId > ,
2496
2468
matched_inputs : & IndexVec < ExpectedIdx , Option < ProvidedIdx > > ,
2497
2469
provided_arg_tys : & IndexVec < ProvidedIdx , ( Ty < ' tcx > , Span ) > ,
@@ -2571,35 +2543,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2571
2543
"expected all arguments to be {} because they need to match the type of this parameter" ,
2572
2544
expected_display_type
2573
2545
)
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
- )
2587
2546
} else {
2588
2547
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" ,
2592
2549
a_or_an( & expected_display_type) ,
2593
2550
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 } ) ) ,
2597
2551
)
2598
2552
} ;
2599
2553
2600
2554
err. span_label ( matched_arg_span, label) ;
2601
2555
}
2602
2556
}
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
+ }
2603
2596
}
2604
2597
2605
2598
struct FindClosureArg < ' tcx > {
0 commit comments