@@ -424,7 +424,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
424
424
"expected formal_input_tys to be the same size as expected_input_tys"
425
425
) ;
426
426
let formal_and_expected_inputs = IndexVec :: from_iter (
427
- formal_input_tys. iter ( ) . copied ( ) . zip_eq ( expected_input_tys. iter ( ) . copied ( ) ) ,
427
+ formal_input_tys
428
+ . iter ( )
429
+ . copied ( )
430
+ . zip_eq ( expected_input_tys. iter ( ) . copied ( ) )
431
+ . map ( |vars| self . resolve_vars_if_possible ( vars) ) ,
428
432
) ;
429
433
430
434
self . set_tainted_by_errors ( self . report_arg_errors (
@@ -639,8 +643,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
639
643
}
640
644
641
645
let ( formal_input_ty, expected_input_ty) = formal_and_expected_inputs[ expected_idx] ;
642
- let formal_input_ty = self . resolve_vars_if_possible ( formal_input_ty) ;
643
- let expected_input_ty = self . resolve_vars_if_possible ( expected_input_ty) ;
644
646
// If either is an error type, we defy the usual convention and consider them to *not* be
645
647
// coercible. This prevents our error message heuristic from trying to pass errors into
646
648
// every argument.
@@ -713,7 +715,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
713
715
// Do we have as many extra provided arguments as the tuple's length?
714
716
// If so, we might have just forgotten to wrap some args in a tuple.
715
717
if let Some ( ty:: Tuple ( tys) ) =
716
- formal_and_expected_inputs. get ( mismatch_idx. into ( ) ) . map ( |tys| self . resolve_vars_if_possible ( tys. 1 ) . kind ( ) )
718
+ formal_and_expected_inputs. get ( mismatch_idx. into ( ) ) . map ( |tys| tys. 1 . kind ( ) )
717
719
// If the tuple is unit, we're not actually wrapping any arguments.
718
720
&& !tys. is_empty ( )
719
721
&& provided_arg_tys. len ( ) == formal_and_expected_inputs. len ( ) - 1 + tys. len ( )
@@ -732,7 +734,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
732
734
provided_arg_tys. iter ( ) . map ( |( ty, _) | * ty) . skip ( mismatch_idx + tys. len ( ) ) ,
733
735
) ,
734
736
) {
735
- if !self . can_coerce ( provided_ty, self . resolve_vars_if_possible ( * expected_ty) ) {
737
+ if !self . can_coerce ( provided_ty, * expected_ty) {
736
738
satisfied = false ;
737
739
break ;
738
740
}
@@ -751,14 +753,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
751
753
if tys. len ( ) == 1 {
752
754
// A tuple wrap suggestion actually occurs within,
753
755
// so don't do anything special here.
754
- let ( formal_ty, expected_ty) =
755
- formal_and_expected_inputs[ mismatch_idx. into ( ) ] ;
756
- let formal_ty = self . resolve_vars_if_possible ( formal_ty) ;
757
- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
758
756
err = self . err_ctxt ( ) . report_and_explain_type_error (
759
757
mk_trace (
760
758
* lo,
761
- ( formal_ty , expected_ty ) ,
759
+ formal_and_expected_inputs [ mismatch_idx . into ( ) ] ,
762
760
provided_arg_tys[ mismatch_idx. into ( ) ] . 0 ,
763
761
) ,
764
762
terr,
@@ -842,10 +840,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
842
840
return true ;
843
841
} ;
844
842
let ( provided_ty, provided_span) = provided_arg_tys[ * provided_idx] ;
845
- let ( formal_ty, expected_ty) = formal_and_expected_inputs[ * expected_idx] ;
846
- let formal_ty = self . resolve_vars_if_possible ( formal_ty) ;
847
- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
848
- let trace = mk_trace ( provided_span, ( formal_ty, expected_ty) , provided_ty) ;
843
+ let trace =
844
+ mk_trace ( provided_span, formal_and_expected_inputs[ * expected_idx] , provided_ty) ;
849
845
if !matches ! ( trace. cause. as_failure_code( * e) , FailureCode :: Error0308 ) {
850
846
let mut err = self . err_ctxt ( ) . report_and_explain_type_error ( trace, * e) ;
851
847
suggest_confusable ( & mut err) ;
@@ -873,8 +869,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
873
869
] = & errors[ ..]
874
870
{
875
871
let ( formal_ty, expected_ty) = formal_and_expected_inputs[ * expected_idx] ;
876
- let formal_ty = self . resolve_vars_if_possible ( formal_ty) ;
877
- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
878
872
let ( provided_ty, provided_arg_span) = provided_arg_tys[ * provided_idx] ;
879
873
let trace = mk_trace ( provided_arg_span, ( formal_ty, expected_ty) , provided_ty) ;
880
874
let mut err = self . err_ctxt ( ) . report_and_explain_type_error ( trace, * err) ;
@@ -896,6 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
896
890
& matched_inputs,
897
891
& provided_arg_tys,
898
892
& formal_and_expected_inputs,
893
+ is_method,
899
894
) ;
900
895
901
896
if let hir:: ExprKind :: MethodCall ( _, rcvr, _, _) = call_expr. kind
@@ -1003,8 +998,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1003
998
match error {
1004
999
Error :: Invalid ( provided_idx, expected_idx, compatibility) => {
1005
1000
let ( formal_ty, expected_ty) = formal_and_expected_inputs[ expected_idx] ;
1006
- let formal_ty = self . resolve_vars_if_possible ( formal_ty) ;
1007
- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
1008
1001
let ( provided_ty, provided_span) = provided_arg_tys[ provided_idx] ;
1009
1002
if let Compatibility :: Incompatible ( error) = compatibility {
1010
1003
let trace = mk_trace ( provided_span, ( formal_ty, expected_ty) , provided_ty) ;
@@ -1109,7 +1102,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1109
1102
match & missing_idxs[ ..] {
1110
1103
& [ expected_idx] => {
1111
1104
let ( _, input_ty) = formal_and_expected_inputs[ expected_idx] ;
1112
- let input_ty = self . resolve_vars_if_possible ( input_ty) ;
1113
1105
let span = if let Some ( ( _, arg_span) ) =
1114
1106
provided_arg_tys. get ( expected_idx. to_provided_idx ( ) )
1115
1107
{
@@ -1132,10 +1124,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1132
1124
& [ first_idx, second_idx] => {
1133
1125
let ( _, first_expected_ty) = formal_and_expected_inputs[ first_idx] ;
1134
1126
let ( _, second_expected_ty) = formal_and_expected_inputs[ second_idx] ;
1135
- let first_expected_ty =
1136
- self . resolve_vars_if_possible ( first_expected_ty) ;
1137
- let second_expected_ty =
1138
- self . resolve_vars_if_possible ( second_expected_ty) ;
1139
1127
let span = if let ( Some ( ( _, first_span) ) , Some ( ( _, second_span) ) ) = (
1140
1128
provided_arg_tys. get ( first_idx. to_provided_idx ( ) ) ,
1141
1129
provided_arg_tys. get ( second_idx. to_provided_idx ( ) ) ,
@@ -1162,14 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1162
1150
}
1163
1151
& [ first_idx, second_idx, third_idx] => {
1164
1152
let ( _, first_expected_ty) = formal_and_expected_inputs[ first_idx] ;
1165
- let first_expected_ty =
1166
- self . resolve_vars_if_possible ( first_expected_ty) ;
1167
1153
let ( _, second_expected_ty) = formal_and_expected_inputs[ second_idx] ;
1168
- let second_expected_ty =
1169
- self . resolve_vars_if_possible ( second_expected_ty) ;
1170
1154
let ( _, third_expected_ty) = formal_and_expected_inputs[ third_idx] ;
1171
- let third_expected_ty =
1172
- self . resolve_vars_if_possible ( third_expected_ty) ;
1173
1155
let span = if let ( Some ( ( _, first_span) ) , Some ( ( _, third_span) ) ) = (
1174
1156
provided_arg_tys. get ( first_idx. to_provided_idx ( ) ) ,
1175
1157
provided_arg_tys. get ( third_idx. to_provided_idx ( ) ) ,
@@ -1229,7 +1211,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1229
1211
) => {
1230
1212
let ( first_provided_ty, first_span) = provided_arg_tys[ first_provided_idx] ;
1231
1213
let ( _, first_expected_ty) = formal_and_expected_inputs[ first_expected_idx] ;
1232
- let first_expected_ty = self . resolve_vars_if_possible ( first_expected_ty) ;
1233
1214
let first_provided_ty_name = if !has_error_or_infer ( [ first_provided_ty] ) {
1234
1215
format ! ( ", found `{first_provided_ty}`" )
1235
1216
} else {
@@ -1242,7 +1223,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1242
1223
1243
1224
let ( second_provided_ty, second_span) = provided_arg_tys[ second_provided_idx] ;
1244
1225
let ( _, second_expected_ty) = formal_and_expected_inputs[ second_expected_idx] ;
1245
- let second_provided_ty = self . resolve_vars_if_possible ( second_provided_ty) ;
1246
1226
let second_provided_ty_name = if !has_error_or_infer ( [ second_provided_ty] ) {
1247
1227
format ! ( ", found `{second_provided_ty}`" )
1248
1228
} else {
@@ -1261,7 +1241,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1261
1241
Error :: Permutation ( args) => {
1262
1242
for ( dst_arg, dest_input) in args {
1263
1243
let ( _, expected_ty) = formal_and_expected_inputs[ dst_arg] ;
1264
- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
1265
1244
let ( provided_ty, provided_span) = provided_arg_tys[ dest_input] ;
1266
1245
let provided_ty_name = if !has_error_or_infer ( [ provided_ty] ) {
1267
1246
format ! ( ", found `{provided_ty}`" )
@@ -1288,6 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1288
1267
& matched_inputs,
1289
1268
& provided_arg_tys,
1290
1269
& formal_and_expected_inputs,
1270
+ is_method,
1291
1271
) ;
1292
1272
1293
1273
// Incorporate the argument changes in the removal suggestion.
@@ -1325,7 +1305,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1325
1305
// To suggest a multipart suggestion when encountering `foo(1, "")` where the def
1326
1306
// was `fn foo(())`.
1327
1307
let ( _, expected_ty) = formal_and_expected_inputs[ expected_idx] ;
1328
- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
1329
1308
suggestions. push ( ( * arg_span, ty_to_snippet ( expected_ty, expected_idx) ) ) ;
1330
1309
}
1331
1310
}
@@ -1402,7 +1381,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1402
1381
} else {
1403
1382
// Propose a placeholder of the correct type
1404
1383
let ( _, expected_ty) = formal_and_expected_inputs[ expected_idx] ;
1405
- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
1406
1384
ty_to_snippet ( expected_ty, expected_idx)
1407
1385
} ;
1408
1386
suggestion += & suggestion_text;
@@ -2475,77 +2453,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2475
2453
matched_inputs : & IndexVec < ExpectedIdx , Option < ProvidedIdx > > ,
2476
2454
provided_arg_tys : & IndexVec < ProvidedIdx , ( Ty < ' tcx > , Span ) > ,
2477
2455
formal_and_expected_inputs : & IndexVec < ExpectedIdx , ( Ty < ' tcx > , Ty < ' tcx > ) > ,
2456
+ is_method : bool ,
2478
2457
) {
2479
2458
let Some ( def_id) = callable_def_id else {
2480
2459
return ;
2481
2460
} ;
2482
2461
2483
- for ( matched_idx, matched_arg) in matched_inputs. iter_enumerated ( ) {
2484
- let Some ( matched_input) = matched_arg else {
2462
+ let params_with_generics = self . get_hir_params_with_generics ( def_id, is_method) ;
2463
+
2464
+ for ( idx, ( generic_param, _) ) in params_with_generics. iter ( ) . enumerate ( ) {
2465
+ if matched_inputs[ idx. into ( ) ] . is_none ( ) {
2466
+ continue ;
2467
+ }
2468
+
2469
+ let Some ( ( _, matched_arg_span) ) = provided_arg_tys. get ( idx. into ( ) ) else {
2485
2470
continue ;
2486
2471
} ;
2487
2472
2488
- let ( _, matched_arg_span) = provided_arg_tys[ * matched_input] ;
2489
- let ( matched_formal_ty, _) = formal_and_expected_inputs[ matched_idx] ;
2490
- let ty:: Infer ( ty:: TyVar ( a) ) = matched_formal_ty. kind ( ) else {
2473
+ let Some ( generic_param) = generic_param else {
2491
2474
continue ;
2492
2475
} ;
2493
2476
2494
- let mut formal_ty_idxs_matched: Vec < usize > = vec ! [ ] ;
2495
- let mut expected_ty_matched = None ;
2496
- for ( input_idx, ( formal_ty, expected_ty) ) in formal_and_expected_inputs
2497
- . iter_enumerated ( )
2498
- // Only care about args after the matched one we're checking.
2499
- //
2500
- // NB: Incompatible should always come after their matching generics.
2501
- // e.g. if we have a function fn f(a: T, b: T, c: T) and we call it with
2502
- // f(1, 2, 3.0) then the first will force T to be an integer, the second
2503
- // then matches and the third is the incompatible argument.
2504
- . filter ( |( idx, _) | * idx > matched_idx)
2505
- {
2506
- if let ty:: Infer ( ty:: TyVar ( b) ) = formal_ty. kind ( ) {
2507
- if self . root_var ( * a) == self . root_var ( * b) {
2508
- formal_ty_idxs_matched. push ( input_idx. into ( ) ) ;
2509
- if expected_ty_matched. is_none ( ) {
2510
- expected_ty_matched = Some ( expected_ty) ;
2511
- }
2477
+ let mut idxs_matched: Vec < usize > = vec ! [ ] ;
2478
+ for ( other_idx, ( _, _) ) in params_with_generics. iter ( ) . enumerate ( ) . filter (
2479
+ |( other_idx, ( other_generic_param, _) ) | {
2480
+ if * other_idx == idx {
2481
+ return false ;
2512
2482
}
2513
- }
2483
+ let Some ( other_generic_param) = other_generic_param else {
2484
+ return false ;
2485
+ } ;
2486
+ if matched_inputs[ ( * other_idx) . into ( ) ] . is_some ( ) {
2487
+ return false ;
2488
+ }
2489
+ other_generic_param. name . ident ( ) == generic_param. name . ident ( )
2490
+ } ,
2491
+ ) {
2492
+ idxs_matched. push ( other_idx. into ( ) ) ;
2514
2493
}
2515
2494
2516
- let Some ( expected_ty ) = expected_ty_matched else {
2495
+ if idxs_matched . len ( ) == 0 {
2517
2496
continue ;
2518
- } ;
2519
-
2520
- let params = self
2521
- . tcx
2522
- . hir ( )
2523
- . get_if_local ( def_id)
2524
- . and_then ( |node| node. body_id ( ) )
2525
- . into_iter ( )
2526
- . flat_map ( |id| self . tcx . hir ( ) . body ( id) . params ) ;
2527
-
2528
- let mut all_pats_matched: Vec < String > = vec ! [ ] ;
2529
- let mut incompatible_pats_matched: Vec < String > = vec ! [ ] ;
2530
- for ( idx, param) in params
2531
- . into_iter ( )
2532
- . enumerate ( )
2533
- . filter ( |( idx, _) | formal_ty_idxs_matched. contains ( idx) )
2534
- {
2535
- let ident = if let hir:: PatKind :: Binding ( _, _, ident, _) = param. pat . kind {
2536
- format ! ( "`{ident}`" )
2537
- } else {
2538
- format ! ( "`idx:{idx}`" )
2539
- } ;
2540
- if matched_inputs[ idx. into ( ) ] . is_none ( ) {
2541
- incompatible_pats_matched. push ( ident. clone ( ) ) ;
2542
- }
2543
- all_pats_matched. push ( ident) ;
2544
2497
}
2545
2498
2546
- let expected_display_type =
2547
- self . resolve_vars_if_possible ( * expected_ty) . sort_string ( self . tcx ) ;
2548
- let label = if all_pats_matched. len ( ) == 0 {
2499
+ let expected_display_type = self
2500
+ . resolve_vars_if_possible ( formal_and_expected_inputs[ idx. into ( ) ] . 1 )
2501
+ . sort_string ( self . tcx ) ;
2502
+ let label = if idxs_matched. len ( ) == params_with_generics. len ( ) - 1 {
2549
2503
format ! (
2550
2504
"expected all arguments to be {} because they need to match the type of this parameter" ,
2551
2505
expected_display_type
@@ -2558,7 +2512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2558
2512
)
2559
2513
} ;
2560
2514
2561
- err. span_label ( matched_arg_span, label) ;
2515
+ err. span_label ( * matched_arg_span, label) ;
2562
2516
}
2563
2517
}
2564
2518
0 commit comments