about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-26 05:02:03 +0000
committerbors <bors@rust-lang.org>2017-09-26 05:02:03 +0000
commit4b8bf391fd595ac0c1ff6e6b7f1ef57cec4eb6da (patch)
tree6aedf1a089045acbc350d4d3c8540a18606eeb6d
parent82ae9682ca3f41f982b881c377a12bb081fead93 (diff)
parent1bfbfb20a181356dece4559b0974ca1fcde02bac (diff)
downloadrust-4b8bf391fd595ac0c1ff6e6b7f1ef57cec4eb6da.tar.gz
rust-4b8bf391fd595ac0c1ff6e6b7f1ef57cec4eb6da.zip
Auto merge of #44735 - tirr-c:issue-42143, r=arielb1
Friendlier error message for closure argument type mismatch

Rebased #42270.
Fixes #42143.

---

`test.rs`:

```rust
fn main() {
    foo(|_: i32, _: usize| ());
}

fn foo<F>(_: F) where F: Fn(&str, usize) {}
```

Before:

```
error[E0281]: type mismatch: `[closure@test.rs:2:9: 2:30]` implements the trait `std::ops::Fn<(i32, usize)>`, but the trait `for<'r> std::ops::Fn<(&'r str, usize)>` is required
 --> test.rs:2:5
  |
2 |     foo(|_: i32, _: usize| ());
  |     ^^^ --------------------- implements `std::ops::Fn<(i32, usize)>`
  |     |
  |     expected &str, found i32
  |     requires `for<'r> std::ops::Fn<(&'r str, usize)>`
  |
  = note: required by `foo`
```

After (early):

```
error[E0631]: type mismatch in closure arguments
 --> test.rs:2:5
  |
2 |     foo(|_: i32, _: usize| ());
  |     ^^^ --------------------- takes arguments of type `i32` and `usize`
  |     |
  |     expected arguments of type `&str` and `usize`
  |
  = note: required by `foo`
```

After (current):

```
error[E0631]: type mismatch in closure arguments
 --> test.rs:2:5
  |
2 |     foo(|_: i32, _: usize| ());
  |     ^^^ --------------------- found signature of `fn(i32, usize) -> _`
  |     |
  |     expected signature of `for<'r> fn(&'r str, usize) -> _`
  |
  = note: required by `foo`
```

~~Compiler output has been changed, and a few tests are failing. Help me writing/fixing tests!~~

r? @nikomatsakis
-rw-r--r--src/librustc/diagnostics.rs5
-rw-r--r--src/librustc/traits/error_reporting.rs141
-rw-r--r--src/librustc/util/ppaux.rs6
-rw-r--r--src/test/ui/mismatched_types/E0281.stderr13
-rw-r--r--src/test/ui/mismatched_types/E0631.rs (renamed from src/test/ui/mismatched_types/E0281.rs)20
-rw-r--r--src/test/ui/mismatched_types/E0631.stderr44
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.rs4
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr28
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.rs21
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr45
-rw-r--r--src/test/ui/mismatched_types/closure-mismatch.stderr7
-rw-r--r--src/test/ui/mismatched_types/fn-variance-1.stderr14
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr7
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr9
14 files changed, 245 insertions, 119 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 6b79f0cde1a..76fba1583f3 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1105,11 +1105,13 @@ already specify all requirements that will be used for every type parameter.
 "##,
 
 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() {
@@ -2052,5 +2054,6 @@ register_diagnostics! {
     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
 }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b491baadd7c..c7c8141f4f7 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -37,7 +37,7 @@ use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
 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;
@@ -711,7 +711,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 }
             }
 
-            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() {
@@ -722,48 +722,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     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()
+                    )
                 }
             }
 
@@ -784,31 +767,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         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>,
@@ -837,6 +795,57 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
         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> {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index f714a5e14c4..214973e3085 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -677,6 +677,12 @@ impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'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)))
diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr
deleted file mode 100644
index 744e8c30939..00000000000
--- a/src/test/ui/mismatched_types/E0281.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-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
-
diff --git a/src/test/ui/mismatched_types/E0281.rs b/src/test/ui/mismatched_types/E0631.rs
index abb66c99fab..e28f15ab0b6 100644
--- a/src/test/ui/mismatched_types/E0281.rs
+++ b/src/test/ui/mismatched_types/E0631.rs
@@ -8,18 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo<F: Fn(usize)>(x: F) { }
+#![feature(unboxed_closures)]
 
+fn foo<F: Fn(usize)>(_: F) {}
+fn bar<F: Fn<usize>>(_: 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`
+    fn f(_: u64) {}
+    foo(|_: isize| {});
+    bar(|_: isize| {});
+    foo(f);
+    bar(f);
 }
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
new file mode 100644
index 00000000000..235e7a10063
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -0,0 +1,44 @@
+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
+
diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs
index 284f82d86eb..f94471a73ca 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.rs
+++ b/src/test/ui/mismatched_types/closure-arg-count.rs
@@ -8,8 +8,12 @@
 // 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!());
 }
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index ca71154e872..3031a77b1e8 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -1,35 +1,45 @@
 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
 
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
new file mode 100644
index 00000000000..aa9dba4c3f4
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
@@ -0,0 +1,21 @@
+// 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);
+}
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
new file mode 100644
index 00000000000..866a024ab08
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -0,0 +1,45 @@
+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
+
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index d928a6a0a8e..a54fd118cc5 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -7,14 +7,13 @@ 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[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`
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index 120fb87cdc8..09a90ef3d6b 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -1,16 +1,22 @@
-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`
 
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index e2e2019307f..71a3a0a5714 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -8,14 +8,13 @@ error[E0599]: no method named `count` found for type `std::iter::Filter<std::ite
            `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
 
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index f14e711b23a..59883649280 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -1,14 +1,11 @@
-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`