Auto merge of #44059 - oli-obk:ok_suggestion, r=nikomatsakis

Suggest `Ok(())` when encountering `Result::<(), E>::Ok()`
This commit is contained in:
bors 2017-08-29 06:18:23 +00:00
commit 6f82dea299
5 changed files with 101 additions and 18 deletions

View File

@ -119,10 +119,10 @@ impl<K: UnifyKey> VarValue<K> {
} }
} }
// We can't use V:LatticeValue, much as I would like to, /// We can't use V:LatticeValue, much as I would like to,
// because frequently the pattern is that V=Option<U> for some /// because frequently the pattern is that V=Option<U> for some
// other type parameter U, and we have no way to say /// other type parameter U, and we have no way to say
// Option<U>:LatticeValue. /// Option<U>:LatticeValue.
impl<K: UnifyKey> UnificationTable<K> { impl<K: UnifyKey> UnificationTable<K> {
pub fn new() -> UnificationTable<K> { pub fn new() -> UnificationTable<K> {
@ -249,7 +249,7 @@ impl<K: UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
fn reverse(_: &mut Vec<VarValue<K>>, _: ()) {} fn reverse(_: &mut Vec<VarValue<K>>, _: ()) {}
} }
// # 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<K> impl<'tcx, K: UnifyKey> UnificationTable<K>
where K::Value: Combine where K::Value: Combine
@ -281,11 +281,11 @@ impl<'tcx, K: UnifyKey> UnificationTable<K>
} }
} }
// # Non-subtyping unification /// # Non-subtyping unification
// ///
// Code to handle keys which carry a value, like ints, /// Code to handle keys which carry a value, like ints,
// floats---anything that doesn't have a subtyping relationship we /// floats---anything that doesn't have a subtyping relationship we
// need to worry about. /// need to worry about.
impl<'tcx, K, V> UnificationTable<K> impl<'tcx, K, V> UnificationTable<K>
where K: UnifyKey<Value = Option<V>>, where K: UnifyKey<Value = Option<V>>,

View File

@ -38,6 +38,7 @@ pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefI
enum CallStep<'tcx> { enum CallStep<'tcx> {
Builtin(Ty<'tcx>), Builtin(Ty<'tcx>),
DeferredClosure(ty::FnSig<'tcx>), DeferredClosure(ty::FnSig<'tcx>),
/// e.g. enum variant constructors
Overloaded(MethodCallee<'tcx>), Overloaded(MethodCallee<'tcx>),
} }

View File

@ -2472,7 +2472,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize, fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
arg_count: usize, error_code: &str, variadic: bool, arg_count: usize, error_code: &str, variadic: bool,
def_span: Option<Span>) { def_span: Option<Span>, sugg_unit: bool) {
let mut err = sess.struct_span_err_with_code(sp, let mut err = sess.struct_span_err_with_code(sp,
&format!("this function takes {}{} parameter{} but {} parameter{} supplied", &format!("this function takes {}{} parameter{} but {} parameter{} supplied",
if variadic {"at least "} else {""}, 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"}), if arg_count == 1 {" was"} else {"s were"}),
error_code); 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 { if let Some(def_s) = def_span {
err.span_label(def_s, "defined here"); 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(); err.emit();
} }
@ -2497,7 +2507,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match tuple_type.sty { match tuple_type.sty {
ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => { 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, arg_types.len(), args.len(),
"E0057", false, def_span); "E0057", false, def_span, false);
expected_arg_tys = &[]; expected_arg_tys = &[];
self.err_args(args.len()) self.err_args(args.len())
} }
@ -2526,13 +2536,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn_inputs.to_vec() fn_inputs.to_vec()
} else { } else {
parameter_count_error(tcx.sess, sp_args, expected_arg_count, 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 = &[]; expected_arg_tys = &[];
self.err_args(supplied_arg_count) self.err_args(supplied_arg_count)
} }
} else { } 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, 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 = &[]; expected_arg_tys = &[];
self.err_args(supplied_arg_count) self.err_args(supplied_arg_count)
}; };

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
}

View File

@ -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