From e8cf5f366263533bd739c4dda9bc8a57ec55b8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 23 Apr 2017 15:36:35 -0700 Subject: [PATCH 1/4] Clean up closure type mismatch errors --- src/librustc/diagnostics.rs | 2 + src/librustc/traits/error_reporting.rs | 66 ++++++++++++++++--- src/librustc/ty/sty.rs | 16 +++++ .../ui/mismatched_types/closure-arg-count.rs | 14 ++++ .../mismatched_types/closure-arg-count.stderr | 43 ++++++++++++ .../ui/mismatched_types/closure-mismatch.rs | 19 ++++++ .../mismatched_types/closure-mismatch.stderr | 21 ++++++ 7 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/mismatched_types/closure-arg-count.rs create mode 100644 src/test/ui/mismatched_types/closure-arg-count.stderr create mode 100644 src/test/ui/mismatched_types/closure-mismatch.rs create mode 100644 src/test/ui/mismatched_types/closure-mismatch.stderr diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 30e9f502abc8c..6f9d9817a447c 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1850,4 +1850,6 @@ 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 } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index ba340a40692c7..dc7e18f8172a3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -35,7 +35,7 @@ use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; use syntax::ast::{self, NodeId}; use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar}; -use ty::error::ExpectedFound; +use ty::error::{ExpectedFound, TypeError}; use ty::fast_reject; use ty::fold::TypeFolder; use ty::subst::Subst; @@ -663,13 +663,63 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if actual_trait_ref.self_ty().references_error() { return; } - struct_span_err!(self.tcx.sess, span, E0281, - "type mismatch: the type `{}` implements the trait `{}`, \ - but the trait `{}` is required ({})", - expected_trait_ref.self_ty(), - expected_trait_ref, - actual_trait_ref, - e) + 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" }); + + 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 + } 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); + + 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 + } + } 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) + } } TraitNotObjectSafe(did) => { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index d59248170344e..be56ac48d3eea 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -68,6 +68,15 @@ pub enum BoundRegion { BrEnv, } +impl BoundRegion { + pub fn is_named(&self) -> bool { + match *self { + BoundRegion::BrNamed(..) => true, + _ => false, + } + } +} + /// When a region changed from late-bound to early-bound when #32330 /// was fixed, its `RegionParameterDef` will have one of these /// structures that we can use to give nicer errors. @@ -1193,6 +1202,13 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + pub fn is_closure(&self) -> bool { + match self.sty { + TyClosure(..) => true, + _ => false, + } + } + pub fn is_integral(&self) -> bool { match self.sty { TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true, diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs new file mode 100644 index 0000000000000..fbe36cd8fd26d --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -0,0 +1,14 @@ +// 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 main() { + [1, 2, 3].sort_by(|tuple| panic!()); + [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); +} diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr new file mode 100644 index 0000000000000..f45734d675b8d --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -0,0 +1,43 @@ +error[E0593]: closure takes 1 parameter but 2 parameters are required here + --> $DIR/closure-arg-count.rs:12:15 + | +12 | [1, 2, 3].sort_by(|tuple| panic!()); + | ^^^^^^^ ---------------- takes 1 parameter + | | + | expected closure that takes 2 parameters + +error[E0593]: closure takes 1 parameter but 2 parameters are required here + --> $DIR/closure-arg-count.rs:12:15 + | +12 | [1, 2, 3].sort_by(|tuple| panic!()); + | ^^^^^^^ ---------------- takes 1 parameter + | | + | expected closure that takes 2 parameters + +error[E0308]: mismatched types + --> $DIR/closure-arg-count.rs:13:24 + | +13 | [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 + | +13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); + | ^^^^^^^ -------------------------- takes 1 parameter + | | + | expected closure that takes 2 parameters + +error[E0593]: closure takes 1 parameter but 2 parameters are required here + --> $DIR/closure-arg-count.rs:13:15 + | +13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); + | ^^^^^^^ -------------------------- takes 1 parameter + | | + | expected closure that takes 2 parameters + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs new file mode 100644 index 0000000000000..91298cb2bbd52 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-mismatch.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. + +trait Foo {} + +impl Foo for T {} + +fn baz(_: T) {} + +fn main() { + baz(|_| ()); +} diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr new file mode 100644 index 0000000000000..09e31b263bc31 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:18:9: 18:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` + --> $DIR/closure-mismatch.rs:18:5 + | +18 | baz(|_| ()); + | ^^^ expected bound lifetime parameter, found concrete lifetime + | + = note: concrete lifetime that was found is lifetime '_#0r + = 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 + --> $DIR/closure-mismatch.rs:18:5 + | +18 | baz(|_| ()); + | ^^^ ------ 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` + +error: aborting due to 2 previous errors + From 366dd1bd3fbabd020cd9acd8f12065e488acc3d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 23 Apr 2017 15:37:16 -0700 Subject: [PATCH 2/4] Avoid spurious ` ` in lifetime diagnostics --- src/librustc/ty/error.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 73d9c8b00ae47..e41202771ccbf 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -117,12 +117,16 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { write!(f, "lifetimes do not intersect") } RegionsInsufficientlyPolymorphic(br, _, _) => { - write!(f, "expected bound lifetime parameter {}, \ - found concrete lifetime", br) + write!(f, + "expected bound lifetime parameter{}{}, found concrete lifetime", + if br.is_named() { " " } else { "" }, + br) } RegionsOverlyPolymorphic(br, _, _) => { - write!(f, "expected concrete lifetime, \ - found bound lifetime parameter {}", br) + write!(f, + "expected concrete lifetime, found bound lifetime parameter{}{}", + if br.is_named() { " " } else { "" }, + br) } Sorts(values) => ty::tls::with(|tcx| { report_maybe_different(f, values.expected.sort_string(tcx), From b52c8c2fcf9ff32e225f57456b65d72b736f3c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 23 Apr 2017 17:54:32 -0700 Subject: [PATCH 3/4] Reorder code, fix unittests --- src/librustc/diagnostics.rs | 29 +++- src/librustc/traits/error_reporting.rs | 149 ++++++++++++------ src/test/compile-fail/E0281.rs | 15 +- src/test/compile-fail/fn-variance-1.rs | 8 +- src/test/compile-fail/issue-36053-2.rs | 7 + .../unboxed-closures-vtable-mismatch.rs | 8 + .../ui/mismatched_types/closure-arg-count.rs | 1 + .../mismatched_types/closure-arg-count.stderr | 58 ++++--- .../mismatched_types/closure-mismatch.stderr | 7 +- 9 files changed, 194 insertions(+), 88 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 6f9d9817a447c..8ef42826faca5 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -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(x: F) { } +fn foo(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(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 } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index dc7e18f8172a3..532a6be356e3d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -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" }); - - 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 + let found_span = expected_trait_ty.ty_to_def_id().and_then(|did| { + 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 { - 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); - - 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 + 1 + }; + let found = if let ty::TyTuple(tys, _) = expected_found.found.sty { + tys.len() + } else { + 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) } } 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, + 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, + 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> { diff --git a/src/test/compile-fail/E0281.rs b/src/test/compile-fail/E0281.rs index d468cd3ff1bf4..abb66c99fab9c 100644 --- a/src/test/compile-fail/E0281.rs +++ b/src/test/compile-fail/E0281.rs @@ -8,9 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo(x: F) { } +fn foo(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` } diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/compile-fail/fn-variance-1.rs index d0d911b6eb936..4bea8177b7c5e 100644 --- a/src/test/compile-fail/fn-variance-1.rs +++ b/src/test/compile-fail/fn-variance-1.rs @@ -19,9 +19,13 @@ fn apply(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` } diff --git a/src/test/compile-fail/issue-36053-2.rs b/src/test/compile-fail/issue-36053-2.rs index 7da529487aa86..7e489621e2102 100644 --- a/src/test/compile-fail/issue-36053-2.rs +++ b/src/test/compile-fail/issue-36053-2.rs @@ -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 } diff --git a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs index 28e8b8db2a46b..7400a27fb6bc1 100644 --- a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs +++ b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs @@ -20,8 +20,16 @@ fn call_itisize>(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); } diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index fbe36cd8fd26d..284f82d86eb92 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -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!()); } diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index f45734d675b8d..c1b880b616273 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -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 diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 09e31b263bc31..5b3eb5931896a 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -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` From b10e2933d939a8412b1358c235f39cb87ae1a450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 25 Apr 2017 17:17:12 -0700 Subject: [PATCH 4/4] Move `cfail` tests to `ui` --- .../mismatched_types}/E0281.rs | 0 src/test/ui/mismatched_types/E0281.stderr | 24 +++++++++++++++ .../mismatched_types}/fn-variance-1.rs | 0 .../ui/mismatched_types/fn-variance-1.stderr | 18 +++++++++++ .../mismatched_types}/issue-36053-2.rs | 0 .../ui/mismatched_types/issue-36053-2.stderr | 28 +++++++++++++++++ .../unboxed-closures-vtable-mismatch.rs | 0 .../unboxed-closures-vtable-mismatch.stderr | 30 +++++++++++++++++++ 8 files changed, 100 insertions(+) rename src/test/{compile-fail => ui/mismatched_types}/E0281.rs (100%) create mode 100644 src/test/ui/mismatched_types/E0281.stderr rename src/test/{compile-fail => ui/mismatched_types}/fn-variance-1.rs (100%) create mode 100644 src/test/ui/mismatched_types/fn-variance-1.stderr rename src/test/{compile-fail => ui/mismatched_types}/issue-36053-2.rs (100%) create mode 100644 src/test/ui/mismatched_types/issue-36053-2.stderr rename src/test/{compile-fail => ui/mismatched_types}/unboxed-closures-vtable-mismatch.rs (100%) create mode 100644 src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr diff --git a/src/test/compile-fail/E0281.rs b/src/test/ui/mismatched_types/E0281.rs similarity index 100% rename from src/test/compile-fail/E0281.rs rename to src/test/ui/mismatched_types/E0281.rs diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr new file mode 100644 index 0000000000000..28a649d4c91a4 --- /dev/null +++ b/src/test/ui/mismatched_types/E0281.stderr @@ -0,0 +1,24 @@ +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,)>` + | | + | requires `std::ops::Fn<(usize,)>` + | expected usize, found struct `std::string::String` + | + = note: required by `foo` + +error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements the trait `std::ops::FnOnce<(std::string::String,)>`, but the trait `std::ops::FnOnce<(usize,)>` is required + --> $DIR/E0281.rs:14:5 + | +14 | foo(|y: String| { }); + | ^^^ --------------- implements `std::ops::FnOnce<(std::string::String,)>` + | | + | requires `std::ops::FnOnce<(usize,)>` + | expected usize, found struct `std::string::String` + | + = note: required by `foo` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/ui/mismatched_types/fn-variance-1.rs similarity index 100% rename from src/test/compile-fail/fn-variance-1.rs rename to src/test/ui/mismatched_types/fn-variance-1.rs diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr new file mode 100644 index 0000000000000..120fb87cdc898 --- /dev/null +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -0,0 +1,18 @@ +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 + --> $DIR/fn-variance-1.rs:21:5 + | +21 | apply(&3, takes_mut); + | ^^^^^ types differ in mutability + | + = 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 + --> $DIR/fn-variance-1.rs:27:5 + | +27 | apply(&mut 3, takes_imm); + | ^^^^^ types differ in mutability + | + = note: required by `apply` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs similarity index 100% rename from src/test/compile-fail/issue-36053-2.rs rename to src/test/ui/mismatched_types/issue-36053-2.rs diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr new file mode 100644 index 0000000000000..adc229aaacc54 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -0,0 +1,28 @@ +error: no method named `count` found for type `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]>` in the current scope + --> $DIR/issue-36053-2.rs:17:55 + | +17 | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | ^^^^^ + | + = note: the method `count` exists but the following trait bounds were not satisfied: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53] : std::ops::FnMut<(&_,)>`, `std::iter::Filter>, [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 + --> $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,)>` + | | + | requires `for<'r> std::ops::FnMut<(&'r &str,)>` + | expected &str, found str + +error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnOnce<(&'r str,)>`, but the trait `for<'r> std::ops::FnOnce<(&'r &str,)>` is required + --> $DIR/issue-36053-2.rs:17:32 + | +17 | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | ^^^^^^ -------------- implements `for<'r> std::ops::FnOnce<(&'r str,)>` + | | + | requires `for<'r> std::ops::FnOnce<(&'r &str,)>` + | expected &str, found str + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs similarity index 100% rename from src/test/compile-fail/unboxed-closures-vtable-mismatch.rs rename to src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr new file mode 100644 index 0000000000000..e100520e561f5 --- /dev/null +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -0,0 +1,30 @@ +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 + --> $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)>` +... +25 | let z = call_it(3, f); + | ^^^^^^^ + | | + | requires `std::ops::FnMut<(isize, isize)>` + | expected isize, found usize + | + = note: required by `call_it` + +error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:22:23: 22:73]` implements the trait `std::ops::FnOnce<(usize, isize)>`, but the trait `std::ops::FnOnce<(isize, isize)>` is required + --> $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::FnOnce<(usize, isize)>` +... +25 | let z = call_it(3, f); + | ^^^^^^^ + | | + | requires `std::ops::FnOnce<(isize, isize)>` + | expected isize, found usize + | + = note: required by `call_it` + +error: aborting due to 2 previous errors +