Auto merge of #38121 - jonathandturner:better_e0061, r=nikomatsakis

Point arg num mismatch errors back to their definition

This PR updates the arg num errors (like E0061) to point back at the function definition where they were defined.

Before:

```
error[E0061]: this function takes 2 parameters but 1 parameter was supplied
  --> E0061.rs:18:7
   |
18 |     f(0);
   |       ^
   |
   = note: the following parameter types were expected:
   = note: u16, &str
```

Now:

```
error[E0061]: this function takes 2 parameters but 1 parameter was supplied
  --> E0061.rs:18:7
   |
11 | fn f(a: u16, b: &str) {}
   | ------------------------ defined here
...
18 |     f(0);
   |       ^ expected 2 parameters
```

This is an incremental improvement.  We probably want to underline only the function name and also have support for functions defined in crates outside of the current crate.

r? @nikomatsakis
This commit is contained in:
bors 2016-12-06 00:17:24 +00:00
commit 09991241fd
12 changed files with 59 additions and 59 deletions

View File

@ -193,9 +193,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-> Ty<'tcx> {
let error_fn_sig;
let fn_sig = match callee_ty.sty {
ty::TyFnDef(.., &ty::BareFnTy {ref sig, ..}) |
ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => sig,
let (fn_sig, def_span) = match callee_ty.sty {
ty::TyFnDef(def_id, .., &ty::BareFnTy {ref sig, ..}) => {
(sig, self.tcx.map.span_if_local(def_id))
}
ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => (sig, None),
ref t => {
let mut unit_variant = None;
if let &ty::TyAdt(adt_def, ..) = t {
@ -241,7 +243,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
variadic: false,
});
&error_fn_sig
(&error_fn_sig, None)
}
};
@ -266,7 +268,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&expected_arg_tys[..],
arg_exprs,
fn_sig.variadic,
TupleArgumentsFlag::DontTupleArguments);
TupleArgumentsFlag::DontTupleArguments,
def_span);
fn_sig.output
}
@ -292,7 +295,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&expected_arg_tys,
arg_exprs,
fn_sig.variadic,
TupleArgumentsFlag::TupleArguments);
TupleArgumentsFlag::TupleArguments,
None);
fn_sig.output
}

View File

@ -2467,17 +2467,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
false, tuple_arguments);
false, tuple_arguments, None);
self.tcx.types.err
} else {
match method_fn_ty.sty {
ty::TyFnDef(.., ref fty) => {
ty::TyFnDef(def_id, .., ref fty) => {
// HACK(eddyb) ignore self in the definition (see above).
let expected_arg_tys = self.expected_types_for_fn_args(sp, expected,
fty.sig.0.output,
&fty.sig.0.inputs[1..]);
self.check_argument_types(sp, &fty.sig.0.inputs[1..], &expected_arg_tys[..],
args_no_rcvr, fty.sig.0.variadic, tuple_arguments);
args_no_rcvr, fty.sig.0.variadic, tuple_arguments,
self.tcx.map.span_if_local(def_id));
fty.sig.0.output
}
_ => {
@ -2495,7 +2497,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected_arg_tys: &[Ty<'tcx>],
args: &'gcx [hir::Expr],
variadic: bool,
tuple_arguments: TupleArgumentsFlag) {
tuple_arguments: TupleArgumentsFlag,
def_span: Option<Span>) {
let tcx = self.tcx;
// Grab the argument types, supplying fresh type variables
@ -2530,9 +2533,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
sp
};
fn parameter_count_error<'tcx>(sess: &Session, sp: Span, fn_inputs: &[Ty<'tcx>],
expected_count: usize, arg_count: usize, error_code: &str,
variadic: bool) {
fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
arg_count: usize, error_code: &str, variadic: bool,
def_span: Option<Span>) {
let mut err = sess.struct_span_err_with_code(sp,
&format!("this function takes {}{} parameter{} but {} parameter{} supplied",
if variadic {"at least "} else {""},
@ -2542,18 +2545,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if arg_count == 1 {" was"} else {"s were"}),
error_code);
let input_types = fn_inputs.iter().map(|i| format!("{:?}", i)).collect::<Vec<String>>();
if input_types.len() > 1 {
err.note("the following parameter types were expected:");
err.note(&input_types.join(", "));
} else if input_types.len() > 0 {
err.note(&format!("the following parameter type was expected: {}",
input_types[0]));
} else {
err.span_label(sp, &format!("expected {}{} parameter{}",
if variadic {"at least "} else {""},
expected_count,
if expected_count == 1 {""} else {"s"}));
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, &format!("defined here"));
}
err.emit();
}
@ -2562,8 +2559,8 @@ 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, fn_inputs, arg_types.len(), args.len(),
"E0057", false);
parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(),
"E0057", false, def_span);
expected_arg_tys = &[];
self.err_args(args.len())
}
@ -2591,14 +2588,14 @@ 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, fn_inputs, expected_arg_count,
supplied_arg_count, "E0060", true);
parameter_count_error(tcx.sess, sp_args, expected_arg_count,
supplied_arg_count, "E0060", true, def_span);
expected_arg_tys = &[];
self.err_args(supplied_arg_count)
}
} else {
parameter_count_error(tcx.sess, sp_args, fn_inputs, expected_arg_count,
supplied_arg_count, "E0061", false);
parameter_count_error(tcx.sess, sp_args, expected_arg_count,
supplied_arg_count, "E0061", false, def_span);
expected_arg_tys = &[];
self.err_args(supplied_arg_count)
};

View File

@ -10,10 +10,11 @@
extern "C" {
fn printf(_: *const u8, ...) -> u32;
//~^ NOTE defined here
}
fn main() {
unsafe { printf(); }
//~^ ERROR E0060
//~| NOTE the following parameter type was expected: *const u8
//~| expected at least 1 parameter
}

View File

@ -9,16 +9,17 @@
// except according to those terms.
fn f(a: u16, b: &str) {}
//~^ NOTE defined here
fn f2(a: u16) {}
//~^ NOTE defined here
fn main() {
f(0);
//~^ ERROR E0061
//~| NOTE the following parameter types were expected:
//~| NOTE u16, &str
//~| expected 2 parameters
f2();
//~^ ERROR E0061
//~| NOTE the following parameter type was expected: u16
//~| expected 1 parameter
}

View File

@ -19,12 +19,12 @@ impl Foo for X {
}
fn print_x(_: &Foo<Item=bool>, extra: &str) {
//~^ NOTE defined here
println!("{}", extra);
}
fn main() {
print_x(X);
//~^ ERROR this function takes 2 parameters but 1 parameter was supplied
//~| NOTE the following parameter types were expected:
//~| NOTE &Foo<Item=bool>, &str
//~^ ERROR E0061
//~| NOTE expected 2 parameters
}

View File

@ -14,7 +14,5 @@ fn main() {
needlesArr.iter().fold(|x, y| {
});
//~^^ ERROR this function takes 2 parameters but 1 parameter was supplied
//~| NOTE the following parameter types were expected
//~| NOTE _, _
// the first error is, um, non-ideal.
//~| NOTE expected 2 parameters
}

View File

@ -11,6 +11,7 @@
// Regression test for issue #4935
fn foo(a: usize) {}
//~^ defined here
fn main() { foo(5, 6) }
//~^ ERROR this function takes 1 parameter but 2 parameters were supplied
//~| NOTE the following parameter type was expected
//~| NOTE expected 1 parameter

View File

@ -13,8 +13,11 @@
pub struct Foo;
impl Foo {
fn zero(self) -> Foo { self }
//~^ NOTE defined here
fn one(self, _: isize) -> Foo { self }
//~^ NOTE defined here
fn two(self, _: isize, _: isize) -> Foo { self }
//~^ NOTE defined here
}
fn main() {
@ -22,10 +25,9 @@ fn main() {
x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied
//~^ NOTE expected 0 parameters
.one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied
//~^ NOTE the following parameter type was expected
//~^ NOTE expected 1 parameter
.two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied
//~^ NOTE the following parameter types were expected
//~| NOTE isize, isize
//~^ NOTE expected 2 parameters
let y = Foo;
y.zero()

View File

@ -13,12 +13,12 @@
// unrelated errors.
fn foo(a: isize, b: isize, c: isize, d:isize) {
//~^ NOTE defined here
panic!();
}
fn main() {
foo(1, 2, 3);
//~^ ERROR this function takes 4 parameters but 3
//~| NOTE the following parameter types were expected:
//~| NOTE isize, isize, isize, isize
//~| NOTE expected 4 parameters
}

View File

@ -41,8 +41,8 @@ fn main() {
//~| NOTE found type
let ans = s();
//~^ ERROR this function takes 1 parameter but 0 parameters were supplied
//~| NOTE the following parameter type was expected
//~| NOTE expected 1 parameter
let ans = s("burma", "shave");
//~^ ERROR this function takes 1 parameter but 2 parameters were supplied
//~| NOTE the following parameter type was expected
//~| NOTE expected 1 parameter
}

View File

@ -10,6 +10,8 @@
extern {
fn foo(f: isize, x: u8, ...);
//~^ defined here
//~| defined here
}
extern "C" fn bar(f: isize, x: u8) {}
@ -17,11 +19,9 @@ extern "C" fn bar(f: isize, x: u8) {}
fn main() {
unsafe {
foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied
//~^ NOTE the following parameter types were expected:
//~| NOTE isize, u8
//~| NOTE expected at least 2 parameters
foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
//~^ NOTE the following parameter types were expected:
//~| NOTE isize, u8
//~| NOTE expected at least 2 parameters
let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
//~^ ERROR: mismatched types

View File

@ -2,17 +2,13 @@ error[E0057]: this function takes 1 parameter but 0 parameters were supplied
--> $DIR/E0057.rs:13:13
|
13 | let a = f(); //~ ERROR E0057
| ^^^
|
= note: the following parameter type was expected: (_,)
| ^^^ expected 1 parameter
error[E0057]: this function takes 1 parameter but 2 parameters were supplied
--> $DIR/E0057.rs:15:15
|
15 | let c = f(2, 3); //~ ERROR E0057
| ^^^^
|
= note: the following parameter type was expected: (_,)
| ^^^^ expected 1 parameter
error: aborting due to 2 previous errors