diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs index 7853bf9478a..5411ae0257a 100644 --- a/src/librustc_data_structures/unify/mod.rs +++ b/src/librustc_data_structures/unify/mod.rs @@ -119,10 +119,10 @@ impl VarValue { } } -// We can't use V:LatticeValue, much as I would like to, -// because frequently the pattern is that V=Option for some -// other type parameter U, and we have no way to say -// Option:LatticeValue. +/// We can't use V:LatticeValue, much as I would like to, +/// because frequently the pattern is that V=Option for some +/// other type parameter U, and we have no way to say +/// Option:LatticeValue. impl UnificationTable { pub fn new() -> UnificationTable { @@ -249,7 +249,7 @@ impl sv::SnapshotVecDelegate for Delegate { fn reverse(_: &mut Vec>, _: ()) {} } -// # Base union-find algorithm, where we are just making sets +/// # Base union-find algorithm, where we are just making sets impl<'tcx, K: UnifyKey> UnificationTable where K::Value: Combine @@ -281,11 +281,11 @@ impl<'tcx, K: UnifyKey> UnificationTable } } -// # Non-subtyping unification -// -// Code to handle keys which carry a value, like ints, -// floats---anything that doesn't have a subtyping relationship we -// need to worry about. +/// # Non-subtyping unification +/// +/// Code to handle keys which carry a value, like ints, +/// floats---anything that doesn't have a subtyping relationship we +/// need to worry about. impl<'tcx, K, V> UnificationTable where K: UnifyKey>, diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 460e2858b22..5b9d4af08e0 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -38,6 +38,7 @@ pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefI enum CallStep<'tcx> { Builtin(Ty<'tcx>), DeferredClosure(ty::FnSig<'tcx>), + /// e.g. enum variant constructors Overloaded(MethodCallee<'tcx>), } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3a18eddaad3..04277272696 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2472,7 +2472,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize, arg_count: usize, error_code: &str, variadic: bool, - def_span: Option) { + 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 {""}, @@ -2482,13 +2482,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if arg_count == 1 {" was"} else {"s were"}), error_code); - err.span_label(sp, format!("expected {}{} parameter{}", - if variadic {"at least "} else {""}, - expected_count, - if expected_count == 1 {""} else {"s"})); if let Some(def_s) = def_span { err.span_label(def_s, "defined here"); } + if sugg_unit { + let mut sugg_span = sp.end_point(); + // remove closing `)` from the span + sugg_span.hi = sugg_span.lo; + err.span_suggestion( + sugg_span, + "expected the unit value `()`. You can create one with a pair of parenthesis", + String::from("()")); + } else { + err.span_label(sp, format!("expected {}{} parameter{}", + if variadic {"at least "} else {""}, + expected_count, + if expected_count == 1 {""} else {"s"})); + } err.emit(); } @@ -2497,7 +2507,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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(), - "E0057", false, def_span); + "E0057", false, def_span, false); expected_arg_tys = &[]; self.err_args(args.len()) } @@ -2526,13 +2536,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_inputs.to_vec() } else { parameter_count_error(tcx.sess, sp_args, expected_arg_count, - supplied_arg_count, "E0060", true, def_span); + supplied_arg_count, "E0060", true, def_span, false); expected_arg_tys = &[]; self.err_args(supplied_arg_count) } } else { + // is the missing argument of type `()`? + let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 { + self.resolve_type_vars_if_possible(&expected_arg_tys[0]).is_nil() + } else if fn_inputs.len() == 1 && supplied_arg_count == 0 { + self.resolve_type_vars_if_possible(&fn_inputs[0]).is_nil() + } else { + false + }; parameter_count_error(tcx.sess, sp_args, expected_arg_count, - supplied_arg_count, "E0061", false, def_span); + supplied_arg_count, "E0061", false, def_span, sugg_unit); expected_arg_tys = &[]; self.err_args(supplied_arg_count) }; diff --git a/src/test/ui/span/missing-unit-argument.rs b/src/test/ui/span/missing-unit-argument.rs new file mode 100644 index 00000000000..2cdab5bedc4 --- /dev/null +++ b/src/test/ui/span/missing-unit-argument.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(():(), ():()) {} +fn bar(():()) {} + +fn main() { + let _: Result<(), String> = Ok(); + foo(); + foo(()); + bar(); +} diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr new file mode 100644 index 00000000000..e508a30d182 --- /dev/null +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -0,0 +1,45 @@ +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/missing-unit-argument.rs:15:33 + | +15 | let _: Result<(), String> = Ok(); + | ^^^^ + | +help: expected the unit value `()`. You can create one with a pair of parenthesis + | +15 | let _: Result<(), String> = Ok(()); + | ^^ + +error[E0061]: this function takes 2 parameters but 0 parameters were supplied + --> $DIR/missing-unit-argument.rs:16:5 + | +11 | fn foo(():(), ():()) {} + | ----------------------- defined here +... +16 | foo(); + | ^^^^^ expected 2 parameters + +error[E0061]: this function takes 2 parameters but 1 parameter was supplied + --> $DIR/missing-unit-argument.rs:17:9 + | +11 | fn foo(():(), ():()) {} + | ----------------------- defined here +... +17 | foo(()); + | ^^ expected 2 parameters + +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/missing-unit-argument.rs:18:5 + | +12 | fn bar(():()) {} + | ---------------- defined here +... +18 | bar(); + | ^^^^^ + | +help: expected the unit value `()`. You can create one with a pair of parenthesis + | +18 | bar(()); + | ^^ + +error: aborting due to 4 previous errors +