about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2017-04-23 17:54:32 -0700
committerEsteban Küber <esteban@kuber.com.ar>2017-04-24 16:44:07 -0700
commitb52c8c2fcf9ff32e225f57456b65d72b736f3c2d (patch)
treed2c4006494b05048ca848c498c1d9390ec3bdca5
parent366dd1bd3fbabd020cd9acd8f12065e488acc3d6 (diff)
downloadrust-b52c8c2fcf9ff32e225f57456b65d72b736f3c2d.tar.gz
rust-b52c8c2fcf9ff32e225f57456b65d72b736f3c2d.zip
Reorder code, fix unittests
-rw-r--r--src/librustc/diagnostics.rs29
-rw-r--r--src/librustc/traits/error_reporting.rs149
-rw-r--r--src/test/compile-fail/E0281.rs15
-rw-r--r--src/test/compile-fail/fn-variance-1.rs8
-rw-r--r--src/test/compile-fail/issue-36053-2.rs7
-rw-r--r--src/test/compile-fail/unboxed-closures-vtable-mismatch.rs8
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.rs1
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr58
-rw-r--r--src/test/ui/mismatched_types/closure-mismatch.stderr7
9 files changed, 194 insertions, 88 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 6f9d9817a44..8ef42826fac 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<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
 }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index dc7e18f8172..532a6be356e 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<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> {
diff --git a/src/test/compile-fail/E0281.rs b/src/test/compile-fail/E0281.rs
index d468cd3ff1b..abb66c99fab 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<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`
 }
diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/compile-fail/fn-variance-1.rs
index d0d911b6eb9..4bea8177b7c 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, 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`
 }
diff --git a/src/test/compile-fail/issue-36053-2.rs b/src/test/compile-fail/issue-36053-2.rs
index 7da529487aa..7e489621e21 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 28e8b8db2a4..7400a27fb6b 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_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);
 }
diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs
index fbe36cd8fd2..284f82d86eb 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 f45734d675b..c1b880b6162 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 09e31b263bc..5b3eb593189 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`