diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7461df8bda509..91ce4511a31cb 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -271,6 +271,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_sig.output(), fn_sig.inputs()); self.check_argument_types(call_expr.span, + call_expr.span, fn_sig.inputs(), &expected_arg_tys[..], arg_exprs, @@ -298,6 +299,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_sig.inputs()); self.check_argument_types(call_expr.span, + call_expr.span, fn_sig.inputs(), &expected_arg_tys, arg_exprs, @@ -315,6 +317,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { method_callee: MethodCallee<'tcx>) -> Ty<'tcx> { let output_type = self.check_method_argument_types(call_expr.span, + call_expr.span, Ok(method_callee), arg_exprs, TupleArgumentsFlag::TupleArguments, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9c6a4abfbd7c0..3506fc071127e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2352,6 +2352,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_method_argument_types(&self, sp: Span, + expr_sp: Span, method: Result, ()>, args_no_rcvr: &'gcx [hir::Expr], tuple_arguments: TupleArgumentsFlag, @@ -2371,7 +2372,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)], }; - self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr, + self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr, false, tuple_arguments, None); return self.tcx.types.err; } @@ -2384,7 +2385,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { method.sig.output(), &method.sig.inputs()[1..] ); - self.check_argument_types(sp, &method.sig.inputs()[1..], &expected_arg_tys[..], + self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..], args_no_rcvr, method.sig.variadic, tuple_arguments, self.tcx.hir.span_if_local(method.def_id)); method.sig.output() @@ -2394,6 +2395,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// method calls and overloaded operators. fn check_argument_types(&self, sp: Span, + expr_sp: Span, fn_inputs: &[Ty<'tcx>], expected_arg_tys: &[Ty<'tcx>], args: &'gcx [hir::Expr], @@ -2434,9 +2436,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { sp }; - fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize, - arg_count: usize, error_code: &str, variadic: bool, - def_span: Option, sugg_unit: bool) { + fn parameter_count_error<'tcx>(sess: &Session, + sp: Span, + expr_sp: Span, + expected_count: usize, + arg_count: usize, + error_code: &str, + variadic: bool, + def_span: Option, + sugg_unit: bool) { let mut err = sess.struct_span_err_with_code(sp, &format!("this function takes {}{} parameter{} but {} parameter{} supplied", if variadic {"at least "} else {""}, @@ -2450,12 +2458,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.span_label(def_s, "defined here"); } if sugg_unit { - let sugg_span = sp.end_point(); + let sugg_span = expr_sp.end_point(); // remove closing `)` from the span let sugg_span = sugg_span.with_hi(sugg_span.lo()); err.span_suggestion( sugg_span, - "expected the unit value `()`. You can create one with a pair of parenthesis", + "expected the unit value `()`; create it with empty parentheses", String::from("()")); } else { err.span_label(sp, format!("expected {}{} parameter{}", @@ -2470,7 +2478,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); match tuple_type.sty { ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => { - parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(), + parameter_count_error(tcx.sess, sp_args, expr_sp, arg_types.len(), args.len(), "E0057", false, def_span, false); expected_arg_tys = &[]; self.err_args(args.len()) @@ -2499,7 +2507,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if supplied_arg_count >= expected_arg_count { fn_inputs.to_vec() } else { - parameter_count_error(tcx.sess, sp_args, expected_arg_count, + parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count, supplied_arg_count, "E0060", true, def_span, false); expected_arg_tys = &[]; self.err_args(supplied_arg_count) @@ -2513,7 +2521,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { false }; - parameter_count_error(tcx.sess, sp_args, expected_arg_count, + parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count, supplied_arg_count, "E0061", false, def_span, sugg_unit); expected_arg_tys = &[]; self.err_args(supplied_arg_count) @@ -2866,7 +2874,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Call the generic checker. - self.check_method_argument_types(span, method, + self.check_method_argument_types(span, + expr.span, + method, &args[1..], DontTupleArguments, expected) diff --git a/src/test/compile-fail/method-call-err-msg.rs b/src/test/ui/method-call-err-msg.rs similarity index 100% rename from src/test/compile-fail/method-call-err-msg.rs rename to src/test/ui/method-call-err-msg.rs diff --git a/src/test/ui/method-call-err-msg.stderr b/src/test/ui/method-call-err-msg.stderr new file mode 100644 index 0000000000000..c39c62daf9efe --- /dev/null +++ b/src/test/ui/method-call-err-msg.stderr @@ -0,0 +1,44 @@ +error[E0061]: this function takes 0 parameters but 1 parameter was supplied + --> $DIR/method-call-err-msg.rs:25:12 + | +15 | fn zero(self) -> Foo { self } + | ----------------------------- defined here +... +25 | x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied + | ^ expected 0 parameters + +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/method-call-err-msg.rs:27:7 + | +17 | fn one(self, _: isize) -> Foo { self } + | -------------------------------------- defined here +... +27 | .one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied + | ^^^ expected 1 parameter + +error[E0061]: this function takes 2 parameters but 1 parameter was supplied + --> $DIR/method-call-err-msg.rs:29:11 + | +19 | fn two(self, _: isize, _: isize) -> Foo { self } + | ------------------------------------------------ defined here +... +29 | .two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied + | ^ expected 2 parameters + +error[E0599]: no method named `take` found for type `Foo` in the current scope + --> $DIR/method-call-err-msg.rs:34:7 + | +34 | .take() //~ ERROR no method named `take` found for type `Foo` in the current scope + | ^^^^ + | + = note: the method `take` exists but the following trait bounds were not satisfied: + `&mut Foo : std::iter::Iterator` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `take`, perhaps you need to implement one of them: + candidate #1: `std::collections::hash::Recover` + candidate #2: `std::io::Read` + candidate #3: `std::iter::Iterator` + candidate #4: `alloc::btree::Recover` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/span/missing-unit-argument.rs b/src/test/ui/span/missing-unit-argument.rs index 2cdab5bedc49a..ba1a999121cc5 100644 --- a/src/test/ui/span/missing-unit-argument.rs +++ b/src/test/ui/span/missing-unit-argument.rs @@ -11,9 +11,17 @@ fn foo(():(), ():()) {} fn bar(():()) {} +struct S; +impl S { + fn baz(self, (): ()) { } + fn generic(self, _: T) { } +} + fn main() { let _: Result<(), String> = Ok(); foo(); foo(()); bar(); + S.baz(); + S.generic::<()>(); } diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index e508a30d1826c..af558d0ab8335 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -1,45 +1,73 @@ error[E0061]: this function takes 1 parameter but 0 parameters were supplied - --> $DIR/missing-unit-argument.rs:15:33 + --> $DIR/missing-unit-argument.rs:21:33 | -15 | let _: Result<(), String> = Ok(); +21 | let _: Result<(), String> = Ok(); | ^^^^ | -help: expected the unit value `()`. You can create one with a pair of parenthesis +help: expected the unit value `()`; create it with empty parentheses | -15 | let _: Result<(), String> = Ok(()); +21 | let _: Result<(), String> = Ok(()); | ^^ error[E0061]: this function takes 2 parameters but 0 parameters were supplied - --> $DIR/missing-unit-argument.rs:16:5 + --> $DIR/missing-unit-argument.rs:22:5 | 11 | fn foo(():(), ():()) {} | ----------------------- defined here ... -16 | foo(); +22 | foo(); | ^^^^^ expected 2 parameters error[E0061]: this function takes 2 parameters but 1 parameter was supplied - --> $DIR/missing-unit-argument.rs:17:9 + --> $DIR/missing-unit-argument.rs:23:9 | 11 | fn foo(():(), ():()) {} | ----------------------- defined here ... -17 | foo(()); +23 | foo(()); | ^^ expected 2 parameters error[E0061]: this function takes 1 parameter but 0 parameters were supplied - --> $DIR/missing-unit-argument.rs:18:5 + --> $DIR/missing-unit-argument.rs:24:5 | 12 | fn bar(():()) {} | ---------------- defined here ... -18 | bar(); +24 | bar(); | ^^^^^ | -help: expected the unit value `()`. You can create one with a pair of parenthesis +help: expected the unit value `()`; create it with empty parentheses | -18 | bar(()); +24 | bar(()); | ^^ -error: aborting due to 4 previous errors +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/missing-unit-argument.rs:25:7 + | +16 | fn baz(self, (): ()) { } + | ------------------------ defined here +... +25 | S.baz(); + | ^^^ + | +help: expected the unit value `()`; create it with empty parentheses + | +25 | S.baz(()); + | ^^ + +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/missing-unit-argument.rs:26:7 + | +17 | fn generic(self, _: T) { } + | ----------------------------- defined here +... +26 | S.generic::<()>(); + | ^^^^^^^ + | +help: expected the unit value `()`; create it with empty parentheses + | +26 | S.generic::<()>(()); + | ^^ + +error: aborting due to 6 previous errors