Skip to content

Commit df095ce

Browse files
committed
Auto merge of #45123 - goffrie:fix-method-unit-call, r=oli-obk
Provide the full span of method calls to `check_argument_types` ... so that it includes the span of the passed arguments, not just the name of the called method. Fixes #44760.
2 parents 8382f39 + bb4d1ca commit df095ce

File tree

6 files changed

+117
-24
lines changed

6 files changed

+117
-24
lines changed

src/librustc_typeck/check/callee.rs

+3
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
271271
fn_sig.output(),
272272
fn_sig.inputs());
273273
self.check_argument_types(call_expr.span,
274+
call_expr.span,
274275
fn_sig.inputs(),
275276
&expected_arg_tys[..],
276277
arg_exprs,
@@ -298,6 +299,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
298299
fn_sig.inputs());
299300

300301
self.check_argument_types(call_expr.span,
302+
call_expr.span,
301303
fn_sig.inputs(),
302304
&expected_arg_tys,
303305
arg_exprs,
@@ -315,6 +317,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
315317
method_callee: MethodCallee<'tcx>)
316318
-> Ty<'tcx> {
317319
let output_type = self.check_method_argument_types(call_expr.span,
320+
call_expr.span,
318321
Ok(method_callee),
319322
arg_exprs,
320323
TupleArgumentsFlag::TupleArguments,

src/librustc_typeck/check/mod.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -2352,6 +2352,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
23522352

23532353
fn check_method_argument_types(&self,
23542354
sp: Span,
2355+
expr_sp: Span,
23552356
method: Result<MethodCallee<'tcx>, ()>,
23562357
args_no_rcvr: &'gcx [hir::Expr],
23572358
tuple_arguments: TupleArgumentsFlag,
@@ -2371,7 +2372,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
23712372
TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)],
23722373
};
23732374

2374-
self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
2375+
self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr,
23752376
false, tuple_arguments, None);
23762377
return self.tcx.types.err;
23772378
}
@@ -2384,7 +2385,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
23842385
method.sig.output(),
23852386
&method.sig.inputs()[1..]
23862387
);
2387-
self.check_argument_types(sp, &method.sig.inputs()[1..], &expected_arg_tys[..],
2388+
self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..],
23882389
args_no_rcvr, method.sig.variadic, tuple_arguments,
23892390
self.tcx.hir.span_if_local(method.def_id));
23902391
method.sig.output()
@@ -2394,6 +2395,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
23942395
/// method calls and overloaded operators.
23952396
fn check_argument_types(&self,
23962397
sp: Span,
2398+
expr_sp: Span,
23972399
fn_inputs: &[Ty<'tcx>],
23982400
expected_arg_tys: &[Ty<'tcx>],
23992401
args: &'gcx [hir::Expr],
@@ -2434,9 +2436,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24342436
sp
24352437
};
24362438

2437-
fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
2438-
arg_count: usize, error_code: &str, variadic: bool,
2439-
def_span: Option<Span>, sugg_unit: bool) {
2439+
fn parameter_count_error<'tcx>(sess: &Session,
2440+
sp: Span,
2441+
expr_sp: Span,
2442+
expected_count: usize,
2443+
arg_count: usize,
2444+
error_code: &str,
2445+
variadic: bool,
2446+
def_span: Option<Span>,
2447+
sugg_unit: bool) {
24402448
let mut err = sess.struct_span_err_with_code(sp,
24412449
&format!("this function takes {}{} parameter{} but {} parameter{} supplied",
24422450
if variadic {"at least "} else {""},
@@ -2450,12 +2458,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24502458
err.span_label(def_s, "defined here");
24512459
}
24522460
if sugg_unit {
2453-
let sugg_span = sp.end_point();
2461+
let sugg_span = expr_sp.end_point();
24542462
// remove closing `)` from the span
24552463
let sugg_span = sugg_span.with_hi(sugg_span.lo());
24562464
err.span_suggestion(
24572465
sugg_span,
2458-
"expected the unit value `()`. You can create one with a pair of parenthesis",
2466+
"expected the unit value `()`; create it with empty parentheses",
24592467
String::from("()"));
24602468
} else {
24612469
err.span_label(sp, format!("expected {}{} parameter{}",
@@ -2470,7 +2478,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24702478
let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
24712479
match tuple_type.sty {
24722480
ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => {
2473-
parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(),
2481+
parameter_count_error(tcx.sess, sp_args, expr_sp, arg_types.len(), args.len(),
24742482
"E0057", false, def_span, false);
24752483
expected_arg_tys = &[];
24762484
self.err_args(args.len())
@@ -2499,7 +2507,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24992507
if supplied_arg_count >= expected_arg_count {
25002508
fn_inputs.to_vec()
25012509
} else {
2502-
parameter_count_error(tcx.sess, sp_args, expected_arg_count,
2510+
parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count,
25032511
supplied_arg_count, "E0060", true, def_span, false);
25042512
expected_arg_tys = &[];
25052513
self.err_args(supplied_arg_count)
@@ -2513,7 +2521,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25132521
} else {
25142522
false
25152523
};
2516-
parameter_count_error(tcx.sess, sp_args, expected_arg_count,
2524+
parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count,
25172525
supplied_arg_count, "E0061", false, def_span, sugg_unit);
25182526
expected_arg_tys = &[];
25192527
self.err_args(supplied_arg_count)
@@ -2866,7 +2874,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
28662874
};
28672875

28682876
// Call the generic checker.
2869-
self.check_method_argument_types(span, method,
2877+
self.check_method_argument_types(span,
2878+
expr.span,
2879+
method,
28702880
&args[1..],
28712881
DontTupleArguments,
28722882
expected)
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error[E0061]: this function takes 0 parameters but 1 parameter was supplied
2+
--> $DIR/method-call-err-msg.rs:25:12
3+
|
4+
15 | fn zero(self) -> Foo { self }
5+
| ----------------------------- defined here
6+
...
7+
25 | x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied
8+
| ^ expected 0 parameters
9+
10+
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
11+
--> $DIR/method-call-err-msg.rs:27:7
12+
|
13+
17 | fn one(self, _: isize) -> Foo { self }
14+
| -------------------------------------- defined here
15+
...
16+
27 | .one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied
17+
| ^^^ expected 1 parameter
18+
19+
error[E0061]: this function takes 2 parameters but 1 parameter was supplied
20+
--> $DIR/method-call-err-msg.rs:29:11
21+
|
22+
19 | fn two(self, _: isize, _: isize) -> Foo { self }
23+
| ------------------------------------------------ defined here
24+
...
25+
29 | .two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied
26+
| ^ expected 2 parameters
27+
28+
error[E0599]: no method named `take` found for type `Foo` in the current scope
29+
--> $DIR/method-call-err-msg.rs:34:7
30+
|
31+
34 | .take() //~ ERROR no method named `take` found for type `Foo` in the current scope
32+
| ^^^^
33+
|
34+
= note: the method `take` exists but the following trait bounds were not satisfied:
35+
`&mut Foo : std::iter::Iterator`
36+
= help: items from traits can only be used if the trait is implemented and in scope
37+
= note: the following traits define an item `take`, perhaps you need to implement one of them:
38+
candidate #1: `std::collections::hash::Recover`
39+
candidate #2: `std::io::Read`
40+
candidate #3: `std::iter::Iterator`
41+
candidate #4: `alloc::btree::Recover`
42+
43+
error: aborting due to 4 previous errors
44+

src/test/ui/span/missing-unit-argument.rs

+8
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,17 @@
1111
fn foo(():(), ():()) {}
1212
fn bar(():()) {}
1313

14+
struct S;
15+
impl S {
16+
fn baz(self, (): ()) { }
17+
fn generic<T>(self, _: T) { }
18+
}
19+
1420
fn main() {
1521
let _: Result<(), String> = Ok();
1622
foo();
1723
foo(());
1824
bar();
25+
S.baz();
26+
S.generic::<()>();
1927
}
+41-13
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,73 @@
11
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
2-
--> $DIR/missing-unit-argument.rs:15:33
2+
--> $DIR/missing-unit-argument.rs:21:33
33
|
4-
15 | let _: Result<(), String> = Ok();
4+
21 | let _: Result<(), String> = Ok();
55
| ^^^^
66
|
7-
help: expected the unit value `()`. You can create one with a pair of parenthesis
7+
help: expected the unit value `()`; create it with empty parentheses
88
|
9-
15 | let _: Result<(), String> = Ok(());
9+
21 | let _: Result<(), String> = Ok(());
1010
| ^^
1111

1212
error[E0061]: this function takes 2 parameters but 0 parameters were supplied
13-
--> $DIR/missing-unit-argument.rs:16:5
13+
--> $DIR/missing-unit-argument.rs:22:5
1414
|
1515
11 | fn foo(():(), ():()) {}
1616
| ----------------------- defined here
1717
...
18-
16 | foo();
18+
22 | foo();
1919
| ^^^^^ expected 2 parameters
2020

2121
error[E0061]: this function takes 2 parameters but 1 parameter was supplied
22-
--> $DIR/missing-unit-argument.rs:17:9
22+
--> $DIR/missing-unit-argument.rs:23:9
2323
|
2424
11 | fn foo(():(), ():()) {}
2525
| ----------------------- defined here
2626
...
27-
17 | foo(());
27+
23 | foo(());
2828
| ^^ expected 2 parameters
2929

3030
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
31-
--> $DIR/missing-unit-argument.rs:18:5
31+
--> $DIR/missing-unit-argument.rs:24:5
3232
|
3333
12 | fn bar(():()) {}
3434
| ---------------- defined here
3535
...
36-
18 | bar();
36+
24 | bar();
3737
| ^^^^^
3838
|
39-
help: expected the unit value `()`. You can create one with a pair of parenthesis
39+
help: expected the unit value `()`; create it with empty parentheses
4040
|
41-
18 | bar(());
41+
24 | bar(());
4242
| ^^
4343

44-
error: aborting due to 4 previous errors
44+
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
45+
--> $DIR/missing-unit-argument.rs:25:7
46+
|
47+
16 | fn baz(self, (): ()) { }
48+
| ------------------------ defined here
49+
...
50+
25 | S.baz();
51+
| ^^^
52+
|
53+
help: expected the unit value `()`; create it with empty parentheses
54+
|
55+
25 | S.baz(());
56+
| ^^
57+
58+
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
59+
--> $DIR/missing-unit-argument.rs:26:7
60+
|
61+
17 | fn generic<T>(self, _: T) { }
62+
| ----------------------------- defined here
63+
...
64+
26 | S.generic::<()>();
65+
| ^^^^^^^
66+
|
67+
help: expected the unit value `()`; create it with empty parentheses
68+
|
69+
26 | S.generic::<()>(());
70+
| ^^
71+
72+
error: aborting due to 6 previous errors
4573

0 commit comments

Comments
 (0)