Skip to content

Commit 1020e30

Browse files
committed
Show types of all args when missing args
When there're missing arguments in a function call, present a list of all the expected types: ```rust fn main() { t(""); } fn t(a: &str, x: String) {} ``` ```bash % rustc file.rs file.rs:3:5: 2:8 error: this function takes 2 parameters but 0 parameters were supplied [E0061] file.rs:3 t(); ^~~ file.rs:3:5: 2:8 help: run `rustc --explain E0061` to see a detailed explanation file.rs:3:5: 2:8 note: the following parameter types were expected: &str, std::string::String error: aborting due to previous error ``` Fixes #33649
1 parent ad5fbaf commit 1020e30

File tree

8 files changed

+55
-33
lines changed

8 files changed

+55
-33
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,29 +2407,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24072407

24082408
let mut expected_arg_tys = expected_arg_tys;
24092409
let expected_arg_count = fn_inputs.len();
2410+
2411+
fn parameter_count_error<'tcx>(sess: &Session, sp: Span, fn_inputs: &[Ty<'tcx>],
2412+
expected_count: usize, arg_count: usize, error_code: &str,
2413+
variadic: bool) {
2414+
let mut err = sess.struct_span_err_with_code(sp,
2415+
&format!("this function takes {}{} parameter{} but {} parameter{} supplied",
2416+
if variadic {"at least "} else {""},
2417+
expected_count,
2418+
if expected_count == 1 {""} else {"s"},
2419+
arg_count,
2420+
if arg_count == 1 {" was"} else {"s were"}),
2421+
error_code);
2422+
let input_types = fn_inputs.iter().map(|i| format!("{:?}", i)).collect::<Vec<String>>();
2423+
if input_types.len() > 0 {
2424+
err.note(&format!("the following parameter type{} expected: {}",
2425+
if expected_count == 1 {" was"} else {"s were"},
2426+
input_types.join(", ")));
2427+
}
2428+
err.emit();
2429+
}
2430+
24102431
let formal_tys = if tuple_arguments == TupleArguments {
24112432
let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
24122433
match tuple_type.sty {
2434+
ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
2435+
parameter_count_error(tcx.sess, sp, fn_inputs, arg_types.len(), args.len(),
2436+
"E0057", false);
2437+
expected_arg_tys = &[];
2438+
self.err_args(args.len())
2439+
}
24132440
ty::TyTuple(arg_types) => {
2414-
if arg_types.len() != args.len() {
2415-
span_err!(tcx.sess, sp, E0057,
2416-
"this function takes {} parameter{} but {} parameter{} supplied",
2417-
arg_types.len(),
2418-
if arg_types.len() == 1 {""} else {"s"},
2419-
args.len(),
2420-
if args.len() == 1 {" was"} else {"s were"});
2421-
expected_arg_tys = &[];
2422-
self.err_args(args.len())
2423-
} else {
2424-
expected_arg_tys = match expected_arg_tys.get(0) {
2425-
Some(&ty) => match ty.sty {
2426-
ty::TyTuple(ref tys) => &tys,
2427-
_ => &[]
2428-
},
2429-
None => &[]
2430-
};
2431-
arg_types.to_vec()
2432-
}
2441+
expected_arg_tys = match expected_arg_tys.get(0) {
2442+
Some(&ty) => match ty.sty {
2443+
ty::TyTuple(ref tys) => &tys,
2444+
_ => &[]
2445+
},
2446+
None => &[]
2447+
};
2448+
arg_types.to_vec()
24332449
}
24342450
_ => {
24352451
span_err!(tcx.sess, sp, E0059,
@@ -2445,23 +2461,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24452461
if supplied_arg_count >= expected_arg_count {
24462462
fn_inputs.to_vec()
24472463
} else {
2448-
span_err!(tcx.sess, sp, E0060,
2449-
"this function takes at least {} parameter{} \
2450-
but {} parameter{} supplied",
2451-
expected_arg_count,
2452-
if expected_arg_count == 1 {""} else {"s"},
2453-
supplied_arg_count,
2454-
if supplied_arg_count == 1 {" was"} else {"s were"});
2464+
parameter_count_error(tcx.sess, sp, fn_inputs, expected_arg_count,
2465+
supplied_arg_count, "E0060", true);
24552466
expected_arg_tys = &[];
24562467
self.err_args(supplied_arg_count)
24572468
}
24582469
} else {
2459-
span_err!(tcx.sess, sp, E0061,
2460-
"this function takes {} parameter{} but {} parameter{} supplied",
2461-
expected_arg_count,
2462-
if expected_arg_count == 1 {""} else {"s"},
2463-
supplied_arg_count,
2464-
if supplied_arg_count == 1 {" was"} else {"s were"});
2470+
parameter_count_error(tcx.sess, sp, fn_inputs, expected_arg_count, supplied_arg_count,
2471+
"E0061", false);
24652472
expected_arg_tys = &[];
24662473
self.err_args(supplied_arg_count)
24672474
};

src/test/compile-fail/issue-18819.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ fn print_x(_: &Foo<Item=bool>, extra: &str) {
2424

2525
fn main() {
2626
print_x(X); //~error this function takes 2 parameters but 1 parameter was supplied
27+
//~^ NOTE the following parameter types were expected: &Foo<Item=bool>, &str
2728
}

src/test/compile-fail/issue-3044.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ fn main() {
1414
needlesArr.iter().fold(|x, y| {
1515
});
1616
//~^^ ERROR this function takes 2 parameters but 1 parameter was supplied
17+
//~^^^ NOTE the following parameter types were expected
1718
//
1819
// the first error is, um, non-ideal.
1920
}

src/test/compile-fail/issue-4935.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212

1313
fn foo(a: usize) {}
1414
fn main() { foo(5, 6) } //~ ERROR this function takes 1 parameter but 2 parameters were supplied
15+
//~^ NOTE the following parameter type was expected

src/test/compile-fail/method-call-err-msg.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ fn main() {
2121
let x = Foo;
2222
x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied
2323
.one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied
24+
//~^ NOTE the following parameter type was expected
2425
.two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied
26+
//~^ NOTE the following parameter types were expected
2527

2628
let y = Foo;
2729
y.zero()
2830
.take() //~ ERROR no method named `take` found for type `Foo` in the current scope
31+
//~^ NOTE the method `take` exists but the following trait bounds were not satisfied
2932
.one(0);
3033
}

src/test/compile-fail/not-enough-arguments.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ fn foo(a: isize, b: isize, c: isize, d:isize) {
1919
fn main() {
2020
foo(1, 2, 3);
2121
//~^ ERROR this function takes 4 parameters but 3
22+
//~^^ NOTE the following parameter types were expected
2223
}

src/test/compile-fail/overloaded-calls-bad.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ fn main() {
3636
y: 3,
3737
};
3838
let ans = s("what"); //~ ERROR mismatched types
39-
let ans = s(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
39+
//~^ NOTE expected isize, found &-ptr
40+
//~| NOTE expected type
41+
//~| NOTE found type
42+
let ans = s();
43+
//~^ ERROR this function takes 1 parameter but 0 parameters were supplied
44+
//~| NOTE the following parameter type was expected
4045
let ans = s("burma", "shave");
4146
//~^ ERROR this function takes 1 parameter but 2 parameters were supplied
47+
//~| NOTE the following parameter type was expected
4248
}

src/test/compile-fail/variadic-ffi-3.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ extern "C" fn bar(f: isize, x: u8) {}
1717
fn main() {
1818
unsafe {
1919
foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
20+
//~^ NOTE the following parameter types were expected
2021
foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
22+
//~^ NOTE the following parameter types were expected
2123

2224
let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
2325
//~^ ERROR: mismatched types

0 commit comments

Comments
 (0)