Skip to content

Commit

Permalink
Fix incorrect suggestion for extra argument with a type error
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Jul 2, 2024
1 parent 49ff390 commit 9f32459
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 0 deletions.
26 changes: 26 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 9f32459

Please sign in to comment.