Reorder code, fix unittests
This commit is contained in:
parent
366dd1bd3f
commit
b52c8c2fcf
@ -1049,18 +1049,19 @@ which expected that trait. This error typically occurs when working with
|
||||
`Fn`-based types. Erroneous code example:
|
||||
|
||||
```compile_fail,E0281
|
||||
fn foo<F: Fn()>(x: F) { }
|
||||
fn foo<F: Fn(usize)>(x: F) { }
|
||||
|
||||
fn main() {
|
||||
// type mismatch: the type ... implements the trait `core::ops::Fn<(_,)>`,
|
||||
// but the trait `core::ops::Fn<()>` is required (expected (), found tuple
|
||||
// type mismatch: ... implements the trait `core::ops::Fn<(String,)>`,
|
||||
// but the trait `core::ops::Fn<(usize,)>` is required
|
||||
// [E0281]
|
||||
foo(|y| { });
|
||||
foo(|y: String| { });
|
||||
}
|
||||
```
|
||||
|
||||
The issue in this case is that `foo` is defined as accepting a `Fn` with no
|
||||
arguments, but the closure we attempted to pass to it requires one argument.
|
||||
The issue in this case is that `foo` is defined as accepting a `Fn` with one
|
||||
argument of type `String`, but the closure we attempted to pass to it requires
|
||||
one arguments of type `usize`.
|
||||
"##,
|
||||
|
||||
E0282: r##"
|
||||
@ -1807,6 +1808,20 @@ makes a difference in practice.)
|
||||
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||
"##,
|
||||
|
||||
E0593: r##"
|
||||
You tried to supply an `Fn`-based type with an incorrect number of arguments
|
||||
than what was expected. Erroneous code example:
|
||||
|
||||
```compile_fail,E0593
|
||||
fn foo<F: Fn()>(x: F) { }
|
||||
|
||||
fn main() {
|
||||
// [E0593] closure takes 1 argument but 0 arguments are required
|
||||
foo(|y| { });
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1850,6 +1865,4 @@ register_diagnostics! {
|
||||
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
|
||||
E0566, // conflicting representation hints
|
||||
E0587, // conflicting packed and align representation hints
|
||||
E0593, // closure argument count mismatch
|
||||
E0594 // closure mismatch
|
||||
}
|
||||
|
@ -664,61 +664,52 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
return;
|
||||
}
|
||||
let expected_trait_ty = expected_trait_ref.self_ty();
|
||||
if expected_trait_ty.is_closure() {
|
||||
if let &TypeError::TupleSize(ref expected_found) = e {
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0593,
|
||||
"closure takes {} parameter{} but {} parameter{} are required here",
|
||||
expected_found.found,
|
||||
if expected_found.found == 1 { "" } else { "s" },
|
||||
expected_found.expected,
|
||||
if expected_found.expected == 1 { "" } else { "s" });
|
||||
let found_span = expected_trait_ty.ty_to_def_id().and_then(|did| {
|
||||
self.tcx.hir.span_if_local(did)
|
||||
});
|
||||
|
||||
err.span_label(span, &format!("expected closure that takes {} parameter{}",
|
||||
expected_found.expected,
|
||||
if expected_found.expected == 1 {
|
||||
""
|
||||
} else {
|
||||
"s"
|
||||
}));
|
||||
let closure_span = expected_trait_ty.ty_to_def_id().and_then(|did| {
|
||||
self.tcx.hir.span_if_local(did)
|
||||
});
|
||||
if let Some(span) = closure_span {
|
||||
err.span_label(span, &format!("takes {} parameter{}",
|
||||
expected_found.found,
|
||||
if expected_found.found == 1 {
|
||||
""
|
||||
} else {
|
||||
"s"
|
||||
}));
|
||||
}
|
||||
err
|
||||
if let &TypeError::TupleSize(ref expected_found) = e {
|
||||
// Expected `|x| { }`, found `|x, y| { }`
|
||||
self.report_arg_count_mismatch(span,
|
||||
found_span,
|
||||
expected_found.expected,
|
||||
expected_found.found,
|
||||
expected_trait_ty.is_closure())
|
||||
} else if let &TypeError::Sorts(ref expected_found) = e {
|
||||
let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty {
|
||||
tys.len()
|
||||
} else {
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0594,
|
||||
"closure mismatch: `{}` implements the trait `{}`, \
|
||||
but the trait `{}` is required",
|
||||
expected_trait_ty,
|
||||
expected_trait_ref,
|
||||
actual_trait_ref);
|
||||
1
|
||||
};
|
||||
let found = if let ty::TyTuple(tys, _) = expected_found.found.sty {
|
||||
tys.len()
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
let closure_span = expected_trait_ty.ty_to_def_id().and_then(|did| {
|
||||
self.tcx.hir.span_if_local(did)
|
||||
});
|
||||
if let Some(span) = closure_span {
|
||||
err.span_label(span, &format!("{}", e));
|
||||
} else {
|
||||
err.note(&format!("{}", e));
|
||||
}
|
||||
err
|
||||
if expected != found {
|
||||
// Expected `|| { }`, found `|x, y| { }`
|
||||
// Expected `fn(x) -> ()`, found `|| { }`
|
||||
self.report_arg_count_mismatch(span,
|
||||
found_span,
|
||||
expected,
|
||||
found,
|
||||
expected_trait_ty.is_closure())
|
||||
} else {
|
||||
self.report_type_argument_mismatch(span,
|
||||
found_span,
|
||||
expected_trait_ty,
|
||||
expected_trait_ref,
|
||||
actual_trait_ref,
|
||||
e)
|
||||
}
|
||||
} else {
|
||||
struct_span_err!(self.tcx.sess, span, E0281,
|
||||
"type mismatch: the type `{}` implements the trait `{}`, \
|
||||
but the trait `{}` is required ({})",
|
||||
expected_trait_ty,
|
||||
expected_trait_ref,
|
||||
actual_trait_ref,
|
||||
e)
|
||||
self.report_type_argument_mismatch(span,
|
||||
found_span,
|
||||
expected_trait_ty,
|
||||
expected_trait_ref,
|
||||
actual_trait_ref,
|
||||
e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -731,6 +722,60 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn report_type_argument_mismatch(&self,
|
||||
span: Span,
|
||||
found_span: Option<Span>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
expected_ref: ty::PolyTraitRef<'tcx>,
|
||||
found_ref: ty::PolyTraitRef<'tcx>,
|
||||
type_error: &TypeError<'tcx>)
|
||||
-> DiagnosticBuilder<'tcx>
|
||||
{
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0281,
|
||||
"type mismatch: `{}` implements the trait `{}`, but the trait `{}` is required",
|
||||
expected_ty,
|
||||
expected_ref,
|
||||
found_ref);
|
||||
|
||||
err.span_label(span, &format!("{}", type_error));
|
||||
|
||||
if let Some(sp) = found_span {
|
||||
err.span_label(span, &format!("requires `{}`", found_ref));
|
||||
err.span_label(sp, &format!("implements `{}`", expected_ref));
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
fn report_arg_count_mismatch(&self,
|
||||
span: Span,
|
||||
found_span: Option<Span>,
|
||||
expected: usize,
|
||||
found: usize,
|
||||
is_closure: bool)
|
||||
-> DiagnosticBuilder<'tcx>
|
||||
{
|
||||
let mut err = struct_span_err!(self.tcx.sess, span, E0593,
|
||||
"{} takes {} argument{} but {} argument{} {} required",
|
||||
if is_closure { "closure" } else { "function" },
|
||||
found,
|
||||
if found == 1 { "" } else { "s" },
|
||||
expected,
|
||||
if expected == 1 { "" } else { "s" },
|
||||
if expected == 1 { "is" } else { "are" });
|
||||
|
||||
err.span_label(span, &format!("expected {} that takes {} argument{}",
|
||||
if is_closure { "closure" } else { "function" },
|
||||
expected,
|
||||
if expected == 1 { "" } else { "s" }));
|
||||
if let Some(span) = found_span {
|
||||
err.span_label(span, &format!("takes {} argument{}",
|
||||
found,
|
||||
if found == 1 { "" } else { "s" }));
|
||||
}
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
@ -8,9 +8,18 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn foo<F: Fn()>(x: F) { }
|
||||
fn foo<F: Fn(usize)>(x: F) { }
|
||||
|
||||
fn main() {
|
||||
foo(|y| { }); //~ ERROR E0281
|
||||
//~^ ERROR E0281
|
||||
foo(|y: String| { });
|
||||
//~^ ERROR E0281
|
||||
//~| ERROR E0281
|
||||
//~| NOTE implements
|
||||
//~| NOTE implements
|
||||
//~| NOTE requires
|
||||
//~| NOTE requires
|
||||
//~| NOTE expected usize, found struct `std::string::String`
|
||||
//~| NOTE expected usize, found struct `std::string::String`
|
||||
//~| NOTE required by `foo`
|
||||
//~| NOTE required by `foo`
|
||||
}
|
||||
|
@ -19,9 +19,13 @@ fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
|
||||
fn main() {
|
||||
apply(&3, takes_imm);
|
||||
apply(&3, takes_mut);
|
||||
//~^ ERROR (types differ in mutability)
|
||||
//~^ ERROR type mismatch
|
||||
//~| NOTE types differ in mutability
|
||||
//~| NOTE required by `apply`
|
||||
|
||||
apply(&mut 3, takes_mut);
|
||||
apply(&mut 3, takes_imm);
|
||||
//~^ ERROR (types differ in mutability)
|
||||
//~^ ERROR type mismatch
|
||||
//~| NOTE types differ in mutability
|
||||
//~| NOTE required by `apply`
|
||||
}
|
||||
|
@ -18,4 +18,11 @@ fn main() {
|
||||
//~^ ERROR no method named `count`
|
||||
//~| ERROR E0281
|
||||
//~| ERROR E0281
|
||||
//~| NOTE expected &str, found str
|
||||
//~| NOTE expected &str, found str
|
||||
//~| NOTE implements
|
||||
//~| NOTE implements
|
||||
//~| NOTE requires
|
||||
//~| NOTE requires
|
||||
//~| NOTE the method `count` exists but the following trait bounds
|
||||
}
|
||||
|
@ -20,8 +20,16 @@ fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
|
||||
|
||||
pub fn main() {
|
||||
let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
|
||||
//~^ NOTE implements
|
||||
//~| NOTE implements
|
||||
let z = call_it(3, f);
|
||||
//~^ ERROR type mismatch
|
||||
//~| ERROR type mismatch
|
||||
//~| NOTE expected isize, found usize
|
||||
//~| NOTE expected isize, found usize
|
||||
//~| NOTE requires
|
||||
//~| NOTE requires
|
||||
//~| NOTE required by `call_it`
|
||||
//~| NOTE required by `call_it`
|
||||
println!("{}", z);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
[1, 2, 3].sort_by(|| panic!());
|
||||
[1, 2, 3].sort_by(|tuple| panic!());
|
||||
[1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
|
||||
}
|
||||
|
@ -1,43 +1,59 @@
|
||||
error[E0593]: closure takes 1 parameter but 2 parameters are required here
|
||||
error[E0593]: closure takes 0 arguments but 2 arguments are required
|
||||
--> $DIR/closure-arg-count.rs:12:15
|
||||
|
|
||||
12 | [1, 2, 3].sort_by(|tuple| panic!());
|
||||
| ^^^^^^^ ---------------- takes 1 parameter
|
||||
12 | [1, 2, 3].sort_by(|| panic!());
|
||||
| ^^^^^^^ ----------- takes 0 arguments
|
||||
| |
|
||||
| expected closure that takes 2 parameters
|
||||
| expected closure that takes 2 arguments
|
||||
|
||||
error[E0593]: closure takes 1 parameter but 2 parameters are required here
|
||||
error[E0593]: closure takes 0 arguments but 2 arguments are required
|
||||
--> $DIR/closure-arg-count.rs:12:15
|
||||
|
|
||||
12 | [1, 2, 3].sort_by(|tuple| panic!());
|
||||
| ^^^^^^^ ---------------- takes 1 parameter
|
||||
12 | [1, 2, 3].sort_by(|| panic!());
|
||||
| ^^^^^^^ ----------- takes 0 arguments
|
||||
| |
|
||||
| expected closure that takes 2 parameters
|
||||
| expected closure that takes 2 arguments
|
||||
|
||||
error[E0593]: closure takes 1 argument but 2 arguments are required
|
||||
--> $DIR/closure-arg-count.rs:13:15
|
||||
|
|
||||
13 | [1, 2, 3].sort_by(|tuple| panic!());
|
||||
| ^^^^^^^ ---------------- takes 1 argument
|
||||
| |
|
||||
| expected closure that takes 2 arguments
|
||||
|
||||
error[E0593]: closure takes 1 argument but 2 arguments are required
|
||||
--> $DIR/closure-arg-count.rs:13:15
|
||||
|
|
||||
13 | [1, 2, 3].sort_by(|tuple| panic!());
|
||||
| ^^^^^^^ ---------------- takes 1 argument
|
||||
| |
|
||||
| expected closure that takes 2 arguments
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/closure-arg-count.rs:13:24
|
||||
--> $DIR/closure-arg-count.rs:14:24
|
||||
|
|
||||
13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
|
||||
14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
|
||||
| ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
|
||||
|
|
||||
= note: expected type `&{integer}`
|
||||
found type `(_, _)`
|
||||
|
||||
error[E0593]: closure takes 1 parameter but 2 parameters are required here
|
||||
--> $DIR/closure-arg-count.rs:13:15
|
||||
error[E0593]: closure takes 1 argument but 2 arguments are required
|
||||
--> $DIR/closure-arg-count.rs:14:15
|
||||
|
|
||||
13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
|
||||
| ^^^^^^^ -------------------------- takes 1 parameter
|
||||
14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
|
||||
| ^^^^^^^ -------------------------- takes 1 argument
|
||||
| |
|
||||
| expected closure that takes 2 parameters
|
||||
| expected closure that takes 2 arguments
|
||||
|
||||
error[E0593]: closure takes 1 parameter but 2 parameters are required here
|
||||
--> $DIR/closure-arg-count.rs:13:15
|
||||
error[E0593]: closure takes 1 argument but 2 arguments are required
|
||||
--> $DIR/closure-arg-count.rs:14:15
|
||||
|
|
||||
13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
|
||||
| ^^^^^^^ -------------------------- takes 1 parameter
|
||||
14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
|
||||
| ^^^^^^^ -------------------------- takes 1 argument
|
||||
| |
|
||||
| expected closure that takes 2 parameters
|
||||
| expected closure that takes 2 arguments
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
@ -8,11 +8,14 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.r
|
||||
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
|
||||
= note: required by `baz`
|
||||
|
||||
error[E0594]: closure mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r (),)>` is required
|
||||
error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r (),)>` is required
|
||||
--> $DIR/closure-mismatch.rs:18:5
|
||||
|
|
||||
18 | baz(|_| ());
|
||||
| ^^^ ------ expected concrete lifetime, found bound lifetime parameter
|
||||
| ^^^ ------ implements `std::ops::Fn<(_,)>`
|
||||
| |
|
||||
| requires `for<'r> std::ops::Fn<(&'r (),)>`
|
||||
| expected concrete lifetime, found bound lifetime parameter
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
|
||||
= note: required by `baz`
|
||||
|
Loading…
Reference in New Issue
Block a user