From dff10d0668a1e89782fb660e033d6a57ab122266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 Feb 2023 15:59:02 +0000 Subject: [PATCH] Re-add replacement logic and add comment explaining it --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 52 ++++++++++++++----- .../argument-suggestions/issue-97484.stderr | 2 +- .../argument-suggestions/mixed_cases.stderr | 11 ++-- .../overloaded-calls-bad.stderr | 11 ++-- .../args-instead-of-tuple-errors.stderr | 20 ++++--- tests/ui/tuple/wrong_argument_ice-3.stderr | 10 ++-- 6 files changed, 71 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 6d164d1c2b271..63b170a3c63b1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1135,20 +1135,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - // // Incorporate the argument changes in the removal suggestion. - // let mut prev = -1; - // for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() { - // if let Some(provided_idx) = provided_idx { - // prev = provided_idx.index() as i64; - // } - // let idx = ProvidedIdx::from_usize((prev + 1) as usize); - // if let None = provided_idx - // && let Some((_, arg_span)) = provided_arg_tys.get(idx) - // { - // let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; - // suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx))); - // } - // } + // Incorporate the argument changes in the removal suggestion. + // When a type is *missing*, and the rest are additional, we want to suggest these with a + // multipart suggestion, but in order to do so we need to figure out *where* the arg that + // was provided but had the wrong type should go, because when looking at `expected_idx` + // that is the position in the argument list in the definition, while `provided_idx` will + // not be present. So we have to look at what the *last* provided position was, and point + // one after to suggest the replacement. FIXME(estebank): This is hacky, and there's + // probably a better more involved change we can make to make this work. + // For example, if we have + // ``` + // fn foo(i32, &'static str) {} + // foo((), (), ()); + // ``` + // what should be suggested is + // ``` + // foo(/* i32 */, /* &str */); + // ``` + // which includes the replacement of the first two `()` for the correct type, and the + // removal of the last `()`. + let mut prev = -1; + for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() { + // We want to point not at the *current* argument expression index, but rather at the + // index position where it *should have been*, which is *after* the previous one. + if let Some(provided_idx) = provided_idx { + prev = provided_idx.index() as i64; + } + let idx = ProvidedIdx::from_usize((prev + 1) as usize); + if let None = provided_idx + && let Some((_, arg_span)) = provided_arg_tys.get(idx) + { + // There is a type that was *not* found anywhere, so it isn't a move, but a + // replacement and we look at what type it should have been. This will allow us + // To suggest a multipart suggestion when encountering `foo(1, "")` where the def + // was `fn foo(())`. + let (_, expected_ty) = formal_and_expected_inputs[expected_idx]; + suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx))); + } + } // If we have less than 5 things to say, it would be useful to call out exactly what's wrong if labels.len() <= 5 { diff --git a/tests/ui/argument-suggestions/issue-97484.stderr b/tests/ui/argument-suggestions/issue-97484.stderr index 2c2797b391149..a86cbbf1802e1 100644 --- a/tests/ui/argument-suggestions/issue-97484.stderr +++ b/tests/ui/argument-suggestions/issue-97484.stderr @@ -20,7 +20,7 @@ LL | foo(&&A, B, C, D, &E, F, G); help: remove the extra arguments | LL - foo(&&A, B, C, D, E, F, G); -LL + foo(&&A, D, E, G); +LL + foo(&&A, D, /* &E */, G); | error: aborting due to previous error diff --git a/tests/ui/argument-suggestions/mixed_cases.stderr b/tests/ui/argument-suggestions/mixed_cases.stderr index cfa5702ab7fe3..c645dd3817929 100644 --- a/tests/ui/argument-suggestions/mixed_cases.stderr +++ b/tests/ui/argument-suggestions/mixed_cases.stderr @@ -2,10 +2,8 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/mixed_cases.rs:10:3 | LL | two_args(1, "", X {}); - | ^^^^^^^^ -------- - | | | | - | | | unexpected argument of type `X` - | | help: remove the extra argument + | ^^^^^^^^ -- ---- unexpected argument of type `X` + | | | expected `f32`, found `&str` | note: function defined here @@ -13,6 +11,11 @@ note: function defined here | LL | fn two_args(_a: i32, _b: f32) {} | ^^^^^^^^ ------- ------- +help: remove the extra argument + | +LL - two_args(1, "", X {}); +LL + two_args(1, /* f32 */); + | error[E0061]: this function takes 3 arguments but 4 arguments were supplied --> $DIR/mixed_cases.rs:11:3 diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.stderr b/tests/ui/mismatched_types/overloaded-calls-bad.stderr index 8032aa32b4f8a..cd483e7ad2c64 100644 --- a/tests/ui/mismatched_types/overloaded-calls-bad.stderr +++ b/tests/ui/mismatched_types/overloaded-calls-bad.stderr @@ -32,10 +32,8 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied --> $DIR/overloaded-calls-bad.rs:37:15 | LL | let ans = s("burma", "shave"); - | ^ ---------------- - | | | | - | | | unexpected argument of type `&'static str` - | | help: remove the extra argument + | ^ ------- ------- unexpected argument of type `&'static str` + | | | expected `isize`, found `&str` | note: implementation defined here @@ -43,6 +41,11 @@ note: implementation defined here | LL | impl FnMut<(isize,)> for S { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove the extra argument + | +LL - let ans = s("burma", "shave"); +LL + let ans = s(/* isize */); + | error[E0308]: mismatched types --> $DIR/overloaded-calls-bad.rs:40:7 diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr index 143363321dac9..510b99bb5af73 100644 --- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr +++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr @@ -2,10 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied --> $DIR/args-instead-of-tuple-errors.rs:6:34 | LL | let _: Option<(i32, bool)> = Some(1, 2); - | ^^^^ --- - | | | - | | unexpected argument of type `{integer}` - | help: remove the extra argument + | ^^^^ - unexpected argument of type `{integer}` | note: expected `(i32, bool)`, found integer --> $DIR/args-instead-of-tuple-errors.rs:6:39 @@ -23,15 +20,17 @@ LL | let _: Option<(i32, bool)> = Some(1, 2); | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL +help: remove the extra argument + | +LL - let _: Option<(i32, bool)> = Some(1, 2); +LL + let _: Option<(i32, bool)> = Some(/* (i32, bool) */); + | error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/args-instead-of-tuple-errors.rs:8:5 | LL | int_bool(1, 2); - | ^^^^^^^^ --- - | | | - | | unexpected argument of type `{integer}` - | help: remove the extra argument + | ^^^^^^^^ - unexpected argument of type `{integer}` | note: expected `(i32, bool)`, found integer --> $DIR/args-instead-of-tuple-errors.rs:8:14 @@ -45,6 +44,11 @@ note: function defined here | LL | fn int_bool(_: (i32, bool)) { | ^^^^^^^^ -------------- +help: remove the extra argument + | +LL - int_bool(1, 2); +LL + int_bool(/* (i32, bool) */); + | error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied --> $DIR/args-instead-of-tuple-errors.rs:11:28 diff --git a/tests/ui/tuple/wrong_argument_ice-3.stderr b/tests/ui/tuple/wrong_argument_ice-3.stderr index 8b4fca4de7d41..7143c959478b4 100644 --- a/tests/ui/tuple/wrong_argument_ice-3.stderr +++ b/tests/ui/tuple/wrong_argument_ice-3.stderr @@ -2,10 +2,7 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied --> $DIR/wrong_argument_ice-3.rs:9:16 | LL | groups.push(new_group, vec![process]); - | ^^^^ --------------- - | | | - | | unexpected argument of type `Vec<&Process>` - | help: remove the extra argument + | ^^^^ ------------- unexpected argument of type `Vec<&Process>` | note: expected `(Vec, Vec)`, found `Vec` --> $DIR/wrong_argument_ice-3.rs:9:21 @@ -16,6 +13,11 @@ LL | groups.push(new_group, vec![process]); found struct `Vec` note: associated function defined here --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +help: remove the extra argument + | +LL - groups.push(new_group, vec![process]); +LL + groups.push(/* (Vec, Vec) */); + | error: aborting due to previous error