Fixes #42143.
E0281 is totally replaced by E0631. UI tests are updated accordingly.
"##,
E0281: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
You tried to supply a type which doesn't implement some trait in a location
which expected that trait. This error typically occurs when working with
`Fn`-based types. Erroneous code example:
-```compile_fail,E0281
+```compile-fail
fn foo<F: Fn(usize)>(x: F) { }
fn main() {
E0566, // conflicting representation hints
E0623, // lifetime mismatch where both parameters are anonymous regions
E0628, // generators cannot have explicit arguments
+ E0631, // type mismatch in closure arguments
E0637, // "'_" is not a valid lifetime bound
}
use std::fmt;
use syntax::ast;
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
-use ty::error::{ExpectedFound, TypeError};
+use ty::error::ExpectedFound;
use ty::fast_reject;
use ty::fold::TypeFolder;
use ty::subst::Subst;
}
}
- OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
+ OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, _) => {
let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref);
if actual_trait_ref.self_ty().references_error() {
self.tcx.hir.span_if_local(did)
});
- 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 {
- 1
+ let self_ty_count =
+ match expected_trait_ref.skip_binder().substs.type_at(1).sty {
+ ty::TyTuple(ref tys, _) => tys.len(),
+ _ => 1,
};
- let found = if let ty::TyTuple(tys, _) = expected_found.found.sty {
- tys.len()
- } else {
- 1
+ let arg_ty_count =
+ match actual_trait_ref.skip_binder().substs.type_at(1).sty {
+ ty::TyTuple(ref tys, _) => tys.len(),
+ _ => 1,
};
-
- 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)
- }
+ if self_ty_count == arg_ty_count {
+ self.report_closure_arg_mismatch(span,
+ found_span,
+ expected_trait_ref,
+ actual_trait_ref)
} else {
- self.report_type_argument_mismatch(span,
- found_span,
- expected_trait_ty,
- expected_trait_ref,
- actual_trait_ref,
- e)
+ // Expected `|| { }`, found `|x, y| { }`
+ // Expected `fn(x) -> ()`, found `|| { }`
+ self.report_arg_count_mismatch(
+ span,
+ found_span,
+ arg_ty_count,
+ self_ty_count,
+ expected_trait_ty.is_closure()
+ )
}
}
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>,
}
err
}
+
+ fn report_closure_arg_mismatch(&self,
+ span: Span,
+ found_span: Option<Span>,
+ expected_ref: ty::PolyTraitRef<'tcx>,
+ found: ty::PolyTraitRef<'tcx>)
+ -> DiagnosticBuilder<'tcx>
+ {
+ fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
+ trait_ref: &ty::TraitRef<'tcx>) -> String {
+ let inputs = trait_ref.substs.type_at(1);
+ let sig = if let ty::TyTuple(inputs, _) = inputs.sty {
+ tcx.mk_fn_sig(
+ inputs.iter().map(|&x| x),
+ tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
+ false,
+ hir::Unsafety::Normal,
+ ::syntax::abi::Abi::Rust
+ )
+ } else {
+ tcx.mk_fn_sig(
+ ::std::iter::once(inputs),
+ tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
+ false,
+ hir::Unsafety::Normal,
+ ::syntax::abi::Abi::Rust
+ )
+ };
+ format!("{}", ty::Binder(sig))
+ }
+
+ let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+ let mut err = struct_span_err!(self.tcx.sess, span, E0631,
+ "type mismatch in {} arguments",
+ if argument_is_closure { "closure" } else { "function" });
+
+ let found_str = format!(
+ "expected signature of `{}`",
+ build_fn_sig_string(self.tcx, found.skip_binder())
+ );
+ err.span_label(span, found_str);
+
+ let found_span = found_span.unwrap_or(span);
+ let expected_str = format!(
+ "found signature of `{}`",
+ build_fn_sig_string(self.tcx, expected_ref.skip_binder())
+ );
+ err.span_label(found_span, expected_str);
+
+ err
+ }
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}
+impl<'tcx> fmt::Display for ty::Binder<ty::FnSig<'tcx>> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
+ }
+}
+
impl<'tcx> fmt::Display for ty::Binder<ty::TraitPredicate<'tcx>> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
+++ /dev/null
-// Copyright 2016 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<F: Fn(usize)>(x: F) { }
-
-fn main() {
- 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`
-}
+++ /dev/null
-error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements the trait `std::ops::Fn<(std::string::String,)>`, but the trait `std::ops::Fn<(usize,)>` is required
- --> $DIR/E0281.rs:14:5
- |
-14 | foo(|y: String| { });
- | ^^^ --------------- implements `std::ops::Fn<(std::string::String,)>`
- | |
- | expected usize, found struct `std::string::String`
- | requires `std::ops::Fn<(usize,)>`
- |
- = note: required by `foo`
-
-error: aborting due to previous error
-
--- /dev/null
+// Copyright 2016 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.
+
+#![feature(unboxed_closures)]
+
+fn foo<F: Fn(usize)>(_: F) {}
+fn bar<F: Fn<usize>>(_: F) {}
+fn main() {
+ fn f(_: u64) {}
+ foo(|_: isize| {});
+ bar(|_: isize| {});
+ foo(f);
+ bar(f);
+}
--- /dev/null
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/E0631.rs:17:5
+ |
+17 | foo(|_: isize| {});
+ | ^^^ ------------- found signature of `fn(isize) -> _`
+ | |
+ | expected signature of `fn(usize) -> _`
+ |
+ = note: required by `foo`
+
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/E0631.rs:18:5
+ |
+18 | bar(|_: isize| {});
+ | ^^^ ------------- found signature of `fn(isize) -> _`
+ | |
+ | expected signature of `fn(usize) -> _`
+ |
+ = note: required by `bar`
+
+error[E0631]: type mismatch in function arguments
+ --> $DIR/E0631.rs:19:5
+ |
+19 | foo(f);
+ | ^^^
+ | |
+ | expected signature of `fn(usize) -> _`
+ | found signature of `fn(u64) -> _`
+ |
+ = note: required by `foo`
+
+error[E0631]: type mismatch in function arguments
+ --> $DIR/E0631.rs:20:5
+ |
+20 | bar(f);
+ | ^^^
+ | |
+ | expected signature of `fn(usize) -> _`
+ | found signature of `fn(u64) -> _`
+ |
+ = note: required by `bar`
+
+error: aborting due to 4 previous errors
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(unboxed_closures)]
+
+fn f<F: Fn<usize>>(_: F) {}
fn main() {
[1, 2, 3].sort_by(|| panic!());
[1, 2, 3].sort_by(|tuple| panic!());
[1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+ f(|| panic!());
}
error[E0593]: closure takes 0 arguments but 2 arguments are required
- --> $DIR/closure-arg-count.rs:12:15
+ --> $DIR/closure-arg-count.rs:15:15
|
-12 | [1, 2, 3].sort_by(|| panic!());
+15 | [1, 2, 3].sort_by(|| panic!());
| ^^^^^^^ ----------- takes 0 arguments
| |
| expected closure that takes 2 arguments
error[E0593]: closure takes 1 argument but 2 arguments are required
- --> $DIR/closure-arg-count.rs:13:15
+ --> $DIR/closure-arg-count.rs:16:15
|
-13 | [1, 2, 3].sort_by(|tuple| panic!());
+16 | [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:14:24
+ --> $DIR/closure-arg-count.rs:17:24
|
-14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
| ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
|
= note: expected type `&{integer}`
found type `(_, _)`
error[E0593]: closure takes 1 argument but 2 arguments are required
- --> $DIR/closure-arg-count.rs:14:15
+ --> $DIR/closure-arg-count.rs:17:15
|
-14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
| ^^^^^^^ -------------------------- takes 1 argument
| |
| expected closure that takes 2 arguments
-error: aborting due to 4 previous errors
+error[E0593]: closure takes 0 arguments but 1 argument is required
+ --> $DIR/closure-arg-count.rs:18:5
+ |
+18 | f(|| panic!());
+ | ^ ----------- takes 0 arguments
+ | |
+ | expected closure that takes 1 argument
+ |
+ = note: required by `f`
+
+error: aborting due to 5 previous errors
--- /dev/null
+// 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 main() {
+ let a = [(1u32, 2u32)];
+ a.iter().map(|_: (u32, u32)| 45);
+ a.iter().map(|_: &(u16, u16)| 45);
+ a.iter().map(|_: (u16, u16)| 45);
+}
+
+fn baz<F: Fn(*mut &u32)>(_: F) {}
+fn _test<'a>(f: fn(*mut &'a u32)) {
+ baz(f);
+}
--- /dev/null
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/closure-arg-type-mismatch.rs:13:14
+ |
+13 | a.iter().map(|_: (u32, u32)| 45);
+ | ^^^ ------------------ found signature of `fn((u32, u32)) -> _`
+ | |
+ | expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/closure-arg-type-mismatch.rs:14:14
+ |
+14 | a.iter().map(|_: &(u16, u16)| 45);
+ | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _`
+ | |
+ | expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/closure-arg-type-mismatch.rs:15:14
+ |
+15 | a.iter().map(|_: (u16, u16)| 45);
+ | ^^^ ------------------ found signature of `fn((u16, u16)) -> _`
+ | |
+ | expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in function arguments
+ --> $DIR/closure-arg-type-mismatch.rs:20:5
+ |
+20 | baz(f);
+ | ^^^
+ | |
+ | expected signature of `for<'r> fn(*mut &'r u32) -> _`
+ | found signature of `fn(*mut &'a u32) -> _`
+ |
+ = note: required by `baz`
+
+error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()`
+ --> $DIR/closure-arg-type-mismatch.rs:20:5
+ |
+20 | baz(f);
+ | ^^^ expected bound lifetime parameter, found concrete lifetime
+ |
+ = note: required by `baz`
+
+error: aborting due to 5 previous errors
+
= 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[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
+error[E0631]: type mismatch in closure arguments
--> $DIR/closure-mismatch.rs:18:5
|
18 | baz(|_| ());
- | ^^^ ------ implements `std::ops::Fn<(_,)>`
+ | ^^^ ------ found signature of `fn(_) -> _`
| |
- | expected concrete lifetime, found bound lifetime parameter
- | requires `for<'r> std::ops::Fn<(&'r (),)>`
+ | expected signature of `for<'r> fn(&'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[E0281]: type mismatch: `fn(&mut isize) {takes_mut}` implements the trait `for<'r> std::ops::FnOnce<(&'r mut isize,)>`, but the trait `std::ops::FnOnce<(&{integer},)>` is required
+error[E0631]: type mismatch in function arguments
--> $DIR/fn-variance-1.rs:21:5
|
21 | apply(&3, takes_mut);
- | ^^^^^ types differ in mutability
+ | ^^^^^
+ | |
+ | expected signature of `fn(&{integer}) -> _`
+ | found signature of `for<'r> fn(&'r mut isize) -> _`
|
= note: required by `apply`
-error[E0281]: type mismatch: `fn(&isize) {takes_imm}` implements the trait `for<'r> std::ops::FnOnce<(&'r isize,)>`, but the trait `std::ops::FnOnce<(&mut {integer},)>` is required
+error[E0631]: type mismatch in function arguments
--> $DIR/fn-variance-1.rs:27:5
|
27 | apply(&mut 3, takes_imm);
- | ^^^^^ types differ in mutability
+ | ^^^^^
+ | |
+ | expected signature of `fn(&mut {integer}) -> _`
+ | found signature of `for<'r> fn(&'r isize) -> _`
|
= note: required by `apply`
`std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
`&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
-error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnMut<(&'r str,)>`, but the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is required
+error[E0631]: type mismatch in closure arguments
--> $DIR/issue-36053-2.rs:17:32
|
17 | once::<&str>("str").fuse().filter(|a: &str| true).count();
- | ^^^^^^ -------------- implements `for<'r> std::ops::FnMut<(&'r str,)>`
+ | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`
| |
- | expected &str, found str
- | requires `for<'r> std::ops::FnMut<(&'r &str,)>`
+ | expected signature of `for<'r> fn(&'r &str) -> _`
error: aborting due to 2 previous errors
-error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:22:23: 22:73]` implements the trait `std::ops::FnMut<(usize, isize)>`, but the trait `std::ops::FnMut<(isize, isize)>` is required
+error[E0631]: type mismatch in closure arguments
--> $DIR/unboxed-closures-vtable-mismatch.rs:25:13
|
22 | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
- | -------------------------------------------------- implements `std::ops::FnMut<(usize, isize)>`
+ | -------------------------------------------------- found signature of `fn(usize, isize) -> _`
...
25 | let z = call_it(3, f);
- | ^^^^^^^
- | |
- | expected isize, found usize
- | requires `std::ops::FnMut<(isize, isize)>`
+ | ^^^^^^^ expected signature of `fn(isize, isize) -> _`
|
= note: required by `call_it`