summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-07-03 23:30:08 +0200
committerGitHub <noreply@github.com>2024-07-03 23:30:08 +0200
commit603130948b532b98862ddd504f3db57eb6f06eeb (patch)
tree74476d0040a51e88a4cba0e6b263b691f2eec82c
parent77fa597079d7854dedf45f8a86fcdf05668dc551 (diff)
parent9f32459c988dec799458f304bbc49ed5dc6ef772 (diff)
Rollup merge of #127253 - chenyukang:yukang-fix-126246-fn-parameters-check, r=estebank
Fix incorrect suggestion for extra argument with a type error Fixes #126246 I tried to fix it in the `find_errors` of ArgMatrix, but seems it's hard to avoid breaking some other test cases. The root cause is we eliminate the first argument even with a type error at here: https://github.com/rust-lang/rust/blob/6292b2af620dbd771ebb687c3a93c69ba8f97268/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs#L664 So the left argument is always treated as extra one. But if there is already a type error, an error message will be generated firstly, which make this issue a trivial one.
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs26
-rw-r--r--tests/ui/argument-suggestions/suggest-better-removing-issue-126246.rs21
-rw-r--r--tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr124
3 files changed, 171 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 4bab25c9727..56dff080867 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -951,6 +951,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return err.emit();
}
+ // Special case, we found an extra argument is provided, which is very common in practice.
+ // but there is a obviously better removing suggestion compared to the current one,
+ // try to find the argument with Error type, if we removed it all the types will become good,
+ // then we will replace the current suggestion.
+ if let [Error::Extra(provided_idx)] = &errors[..] {
+ let remove_idx_is_perfect = |idx: usize| -> bool {
+ let removed_arg_tys = provided_arg_tys
+ .iter()
+ .enumerate()
+ .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
+ .collect::<IndexVec<ProvidedIdx, _>>();
+ std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
+ |((expected_ty, _), (provided_ty, _))| {
+ !provided_ty.references_error()
+ && self.can_coerce(*provided_ty, *expected_ty)
+ },
+ )
+ };
+
+ if !remove_idx_is_perfect(provided_idx.as_usize()) {
+ if let Some(i) = (0..provided_args.len()).find(|&i| remove_idx_is_perfect(i)) {
+ errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
+ }
+ }
+ }
+
let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
struct_span_code_err!(
self.dcx(),
diff --git a/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.rs b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.rs
new file mode 100644
index 00000000000..fa1802283c3
--- /dev/null
+++ b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.rs
@@ -0,0 +1,21 @@
+fn add_one(x: i32) -> i32 {
+ x + 1
+}
+
+fn add_two(x: i32, y: i32) -> i32 {
+ x + y
+}
+
+fn main() {
+ add_one(2, 2); //~ ERROR this function takes 1 argument but 2 arguments were supplied
+ add_one(no_such_local, 10); //~ ERROR cannot find value `no_such_local` in this scope
+ //~| ERROR this function takes 1 argument but 2 arguments were supplied
+ add_one(10, no_such_local); //~ ERROR cannot find value `no_such_local` in this scope
+ //~| ERROR this function takes 1 argument but 2 arguments were supplied
+ add_two(10, no_such_local, 10); //~ ERROR cannot find value `no_such_local` in this scope
+ //~| ERROR this function takes 2 arguments but 3 arguments were supplied
+ add_two(no_such_local, 10, 10); //~ ERROR cannot find value `no_such_local` in this scope
+ //~| ERROR this function takes 2 arguments but 3 arguments were supplied
+ add_two(10, 10, no_such_local); //~ ERROR cannot find value `no_such_local` in this scope
+ //~| ERROR this function takes 2 arguments but 3 arguments were supplied
+}
diff --git a/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr
new file mode 100644
index 00000000000..7c4daa3ffe9
--- /dev/null
+++ b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr
@@ -0,0 +1,124 @@
+error[E0425]: cannot find value `no_such_local` in this scope
+ --> $DIR/suggest-better-removing-issue-126246.rs:11:13
+ |
+LL | add_one(no_such_local, 10);
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `no_such_local` in this scope
+ --> $DIR/suggest-better-removing-issue-126246.rs:13:17
+ |
+LL | add_one(10, no_such_local);
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `no_such_local` in this scope
+ --> $DIR/suggest-better-removing-issue-126246.rs:15:17
+ |
+LL | add_two(10, no_such_local, 10);
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `no_such_local` in this scope
+ --> $DIR/suggest-better-removing-issue-126246.rs:17:13
+ |
+LL | add_two(no_such_local, 10, 10);
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `no_such_local` in this scope
+ --> $DIR/suggest-better-removing-issue-126246.rs:19:21
+ |
+LL | add_two(10, 10, no_such_local);
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+ --> $DIR/suggest-better-removing-issue-126246.rs:10:5
+ |
+LL | add_one(2, 2);
+ | ^^^^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
+ |
+note: function defined here
+ --> $DIR/suggest-better-removing-issue-126246.rs:1:4
+ |
+LL | fn add_one(x: i32) -> i32 {
+ | ^^^^^^^ ------
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+ --> $DIR/suggest-better-removing-issue-126246.rs:11:5
+ |
+LL | add_one(no_such_local, 10);
+ | ^^^^^^^ ---------------
+ | |
+ | unexpected argument
+ | help: remove the extra argument
+ |
+note: function defined here
+ --> $DIR/suggest-better-removing-issue-126246.rs:1:4
+ |
+LL | fn add_one(x: i32) -> i32 {
+ | ^^^^^^^ ------
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+ --> $DIR/suggest-better-removing-issue-126246.rs:13:5
+ |
+LL | add_one(10, no_such_local);
+ | ^^^^^^^ ---------------
+ | | |
+ | | unexpected argument
+ | help: remove the extra argument
+ |
+note: function defined here
+ --> $DIR/suggest-better-removing-issue-126246.rs:1:4
+ |
+LL | fn add_one(x: i32) -> i32 {
+ | ^^^^^^^ ------
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/suggest-better-removing-issue-126246.rs:15:5
+ |
+LL | add_two(10, no_such_local, 10);
+ | ^^^^^^^ ---------------
+ | | |
+ | | unexpected argument
+ | help: remove the extra argument
+ |
+note: function defined here
+ --> $DIR/suggest-better-removing-issue-126246.rs:5:4
+ |
+LL | fn add_two(x: i32, y: i32) -> i32 {
+ | ^^^^^^^ ------ ------
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/suggest-better-removing-issue-126246.rs:17:5
+ |
+LL | add_two(no_such_local, 10, 10);
+ | ^^^^^^^ ---------------
+ | |
+ | unexpected argument
+ | help: remove the extra argument
+ |
+note: function defined here
+ --> $DIR/suggest-better-removing-issue-126246.rs:5:4
+ |
+LL | fn add_two(x: i32, y: i32) -> i32 {
+ | ^^^^^^^ ------ ------
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/suggest-better-removing-issue-126246.rs:19:5
+ |
+LL | add_two(10, 10, no_such_local);
+ | ^^^^^^^ ---------------
+ | | |
+ | | unexpected argument
+ | help: remove the extra argument
+ |
+note: function defined here
+ --> $DIR/suggest-better-removing-issue-126246.rs:5:4
+ |
+LL | fn add_two(x: i32, y: i32) -> i32 {
+ | ^^^^^^^ ------ ------
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0061, E0425.
+For more information about an error, try `rustc --explain E0061`.