@@ -1135,20 +1135,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11351135 }
11361136 }
11371137
1138- // // Incorporate the argument changes in the removal suggestion.
1139- // let mut prev = -1;
1140- // for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1141- // if let Some(provided_idx) = provided_idx {
1142- // prev = provided_idx.index() as i64;
1143- // }
1144- // let idx = ProvidedIdx::from_usize((prev + 1) as usize);
1145- // if let None = provided_idx
1146- // && let Some((_, arg_span)) = provided_arg_tys.get(idx)
1147- // {
1148- // let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1149- // suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
1150- // }
1151- // }
1138+ // Incorporate the argument changes in the removal suggestion.
1139+ // When a type is *missing*, and the rest are additional, we want to suggest these with a
1140+ // multipart suggestion, but in order to do so we need to figure out *where* the arg that
1141+ // was provided but had the wrong type should go, because when looking at `expected_idx`
1142+ // that is the position in the argument list in the definition, while `provided_idx` will
1143+ // not be present. So we have to look at what the *last* provided position was, and point
1144+ // one after to suggest the replacement. FIXME(estebank): This is hacky, and there's
1145+ // probably a better more involved change we can make to make this work.
1146+ // For example, if we have
1147+ // ```
1148+ // fn foo(i32, &'static str) {}
1149+ // foo((), (), ());
1150+ // ```
1151+ // what should be suggested is
1152+ // ```
1153+ // foo(/* i32 */, /* &str */);
1154+ // ```
1155+ // which includes the replacement of the first two `()` for the correct type, and the
1156+ // removal of the last `()`.
1157+ let mut prev = -1 ;
1158+ for ( expected_idx, provided_idx) in matched_inputs. iter_enumerated ( ) {
1159+ // We want to point not at the *current* argument expression index, but rather at the
1160+ // index position where it *should have been*, which is *after* the previous one.
1161+ if let Some ( provided_idx) = provided_idx {
1162+ prev = provided_idx. index ( ) as i64 ;
1163+ }
1164+ let idx = ProvidedIdx :: from_usize ( ( prev + 1 ) as usize ) ;
1165+ if let None = provided_idx
1166+ && let Some ( ( _, arg_span) ) = provided_arg_tys. get ( idx)
1167+ {
1168+ // There is a type that was *not* found anywhere, so it isn't a move, but a
1169+ // replacement and we look at what type it should have been. This will allow us
1170+ // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
1171+ // was `fn foo(())`.
1172+ let ( _, expected_ty) = formal_and_expected_inputs[ expected_idx] ;
1173+ suggestions. push ( ( * arg_span, ty_to_snippet ( expected_ty, expected_idx) ) ) ;
1174+ }
1175+ }
11521176
11531177 // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
11541178 if labels. len ( ) <= 5 {
0 commit comments