@@ -424,7 +424,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
424424 "expected formal_input_tys to be the same size as expected_input_tys"
425425 ) ;
426426 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) ) ,
428432 ) ;
429433
430434 self . set_tainted_by_errors ( self . report_arg_errors (
@@ -639,8 +643,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
639643 }
640644
641645 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) ;
644646 // If either is an error type, we defy the usual convention and consider them to *not* be
645647 // coercible. This prevents our error message heuristic from trying to pass errors into
646648 // every argument.
@@ -713,7 +715,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
713715 // Do we have as many extra provided arguments as the tuple's length?
714716 // If so, we might have just forgotten to wrap some args in a tuple.
715717 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 ( ) )
717719 // If the tuple is unit, we're not actually wrapping any arguments.
718720 && !tys. is_empty ( )
719721 && provided_arg_tys. len ( ) == formal_and_expected_inputs. len ( ) - 1 + tys. len ( )
@@ -732,7 +734,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
732734 provided_arg_tys. iter ( ) . map ( |( ty, _) | * ty) . skip ( mismatch_idx + tys. len ( ) ) ,
733735 ) ,
734736 ) {
735- if !self . can_coerce ( provided_ty, self . resolve_vars_if_possible ( * expected_ty) ) {
737+ if !self . can_coerce ( provided_ty, * expected_ty) {
736738 satisfied = false ;
737739 break ;
738740 }
@@ -751,14 +753,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
751753 if tys. len ( ) == 1 {
752754 // A tuple wrap suggestion actually occurs within,
753755 // 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) ;
758756 err = self . err_ctxt ( ) . report_and_explain_type_error (
759757 mk_trace (
760758 * lo,
761- ( formal_ty , expected_ty ) ,
759+ formal_and_expected_inputs [ mismatch_idx . into ( ) ] ,
762760 provided_arg_tys[ mismatch_idx. into ( ) ] . 0 ,
763761 ) ,
764762 terr,
@@ -842,10 +840,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
842840 return true ;
843841 } ;
844842 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) ;
849845 if !matches ! ( trace. cause. as_failure_code( * e) , FailureCode :: Error0308 ) {
850846 let mut err = self . err_ctxt ( ) . report_and_explain_type_error ( trace, * e) ;
851847 suggest_confusable ( & mut err) ;
@@ -873,8 +869,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
873869 ] = & errors[ ..]
874870 {
875871 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) ;
878872 let ( provided_ty, provided_arg_span) = provided_arg_tys[ * provided_idx] ;
879873 let trace = mk_trace ( provided_arg_span, ( formal_ty, expected_ty) , provided_ty) ;
880874 let mut err = self . err_ctxt ( ) . report_and_explain_type_error ( trace, * err) ;
@@ -896,6 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
896890 & matched_inputs,
897891 & provided_arg_tys,
898892 & formal_and_expected_inputs,
893+ is_method,
899894 ) ;
900895
901896 if let hir:: ExprKind :: MethodCall ( _, rcvr, _, _) = call_expr. kind
@@ -1003,8 +998,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1003998 match error {
1004999 Error :: Invalid ( provided_idx, expected_idx, compatibility) => {
10051000 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) ;
10081001 let ( provided_ty, provided_span) = provided_arg_tys[ provided_idx] ;
10091002 if let Compatibility :: Incompatible ( error) = compatibility {
10101003 let trace = mk_trace ( provided_span, ( formal_ty, expected_ty) , provided_ty) ;
@@ -1109,7 +1102,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11091102 match & missing_idxs[ ..] {
11101103 & [ expected_idx] => {
11111104 let ( _, input_ty) = formal_and_expected_inputs[ expected_idx] ;
1112- let input_ty = self . resolve_vars_if_possible ( input_ty) ;
11131105 let span = if let Some ( ( _, arg_span) ) =
11141106 provided_arg_tys. get ( expected_idx. to_provided_idx ( ) )
11151107 {
@@ -1132,10 +1124,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11321124 & [ first_idx, second_idx] => {
11331125 let ( _, first_expected_ty) = formal_and_expected_inputs[ first_idx] ;
11341126 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) ;
11391127 let span = if let ( Some ( ( _, first_span) ) , Some ( ( _, second_span) ) ) = (
11401128 provided_arg_tys. get ( first_idx. to_provided_idx ( ) ) ,
11411129 provided_arg_tys. get ( second_idx. to_provided_idx ( ) ) ,
@@ -1162,14 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11621150 }
11631151 & [ first_idx, second_idx, third_idx] => {
11641152 let ( _, first_expected_ty) = formal_and_expected_inputs[ first_idx] ;
1165- let first_expected_ty =
1166- self . resolve_vars_if_possible ( first_expected_ty) ;
11671153 let ( _, second_expected_ty) = formal_and_expected_inputs[ second_idx] ;
1168- let second_expected_ty =
1169- self . resolve_vars_if_possible ( second_expected_ty) ;
11701154 let ( _, third_expected_ty) = formal_and_expected_inputs[ third_idx] ;
1171- let third_expected_ty =
1172- self . resolve_vars_if_possible ( third_expected_ty) ;
11731155 let span = if let ( Some ( ( _, first_span) ) , Some ( ( _, third_span) ) ) = (
11741156 provided_arg_tys. get ( first_idx. to_provided_idx ( ) ) ,
11751157 provided_arg_tys. get ( third_idx. to_provided_idx ( ) ) ,
@@ -1229,7 +1211,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12291211 ) => {
12301212 let ( first_provided_ty, first_span) = provided_arg_tys[ first_provided_idx] ;
12311213 let ( _, first_expected_ty) = formal_and_expected_inputs[ first_expected_idx] ;
1232- let first_expected_ty = self . resolve_vars_if_possible ( first_expected_ty) ;
12331214 let first_provided_ty_name = if !has_error_or_infer ( [ first_provided_ty] ) {
12341215 format ! ( ", found `{first_provided_ty}`" )
12351216 } else {
@@ -1242,7 +1223,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12421223
12431224 let ( second_provided_ty, second_span) = provided_arg_tys[ second_provided_idx] ;
12441225 let ( _, second_expected_ty) = formal_and_expected_inputs[ second_expected_idx] ;
1245- let second_provided_ty = self . resolve_vars_if_possible ( second_provided_ty) ;
12461226 let second_provided_ty_name = if !has_error_or_infer ( [ second_provided_ty] ) {
12471227 format ! ( ", found `{second_provided_ty}`" )
12481228 } else {
@@ -1261,7 +1241,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12611241 Error :: Permutation ( args) => {
12621242 for ( dst_arg, dest_input) in args {
12631243 let ( _, expected_ty) = formal_and_expected_inputs[ dst_arg] ;
1264- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
12651244 let ( provided_ty, provided_span) = provided_arg_tys[ dest_input] ;
12661245 let provided_ty_name = if !has_error_or_infer ( [ provided_ty] ) {
12671246 format ! ( ", found `{provided_ty}`" )
@@ -1288,6 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12881267 & matched_inputs,
12891268 & provided_arg_tys,
12901269 & formal_and_expected_inputs,
1270+ is_method,
12911271 ) ;
12921272
12931273 // Incorporate the argument changes in the removal suggestion.
@@ -1325,7 +1305,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13251305 // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
13261306 // was `fn foo(())`.
13271307 let ( _, expected_ty) = formal_and_expected_inputs[ expected_idx] ;
1328- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
13291308 suggestions. push ( ( * arg_span, ty_to_snippet ( expected_ty, expected_idx) ) ) ;
13301309 }
13311310 }
@@ -1402,7 +1381,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14021381 } else {
14031382 // Propose a placeholder of the correct type
14041383 let ( _, expected_ty) = formal_and_expected_inputs[ expected_idx] ;
1405- let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
14061384 ty_to_snippet ( expected_ty, expected_idx)
14071385 } ;
14081386 suggestion += & suggestion_text;
@@ -2475,77 +2453,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24752453 matched_inputs : & IndexVec < ExpectedIdx , Option < ProvidedIdx > > ,
24762454 provided_arg_tys : & IndexVec < ProvidedIdx , ( Ty < ' tcx > , Span ) > ,
24772455 formal_and_expected_inputs : & IndexVec < ExpectedIdx , ( Ty < ' tcx > , Ty < ' tcx > ) > ,
2456+ is_method : bool ,
24782457 ) {
24792458 let Some ( def_id) = callable_def_id else {
24802459 return ;
24812460 } ;
24822461
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 {
24852470 continue ;
24862471 } ;
24872472
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 {
24912474 continue ;
24922475 } ;
24932476
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 ;
25122482 }
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 ( ) ) ;
25142493 }
25152494
2516- let Some ( expected_ty ) = expected_ty_matched else {
2495+ if idxs_matched . len ( ) == 0 {
25172496 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) ;
25442497 }
25452498
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 {
25492503 format ! (
25502504 "expected all arguments to be {} because they need to match the type of this parameter" ,
25512505 expected_display_type
@@ -2558,7 +2512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25582512 )
25592513 } ;
25602514
2561- err. span_label ( matched_arg_span, label) ;
2515+ err. span_label ( * matched_arg_span, label) ;
25622516 }
25632517 }
25642518
0 commit comments