about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs9
-rw-r--r--library/core/src/ops/function.rs12
-rw-r--r--src/test/ui/closures/coerce-unsafe-to-closure.stderr1
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr3
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr3
5 files changed, 28 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index d2b1fe2e0df..31b92d52beb 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -208,6 +208,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 flags.push((sym::_Self, Some("&[]".to_owned())));
             }
 
+            if self_ty.is_fn() {
+                let fn_sig = self_ty.fn_sig(self.tcx);
+                let shortname = match fn_sig.unsafety() {
+                    hir::Unsafety::Normal => "fn",
+                    hir::Unsafety::Unsafe => "unsafe fn",
+                };
+                flags.push((sym::_Self, Some(shortname.to_owned())));
+            }
+
             if let ty::Array(aty, len) = self_ty.kind() {
                 flags.push((sym::_Self, Some("[]".to_owned())));
                 flags.push((sym::_Self, Some(format!("[{}]", aty))));
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index e5c4798afcb..a7b28471bfe 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -59,6 +59,10 @@
         Args = "()",
         note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
     ),
+    on(
+        _Self = "unsafe fn",
+        note = "unsafe functions must be wrapped in closures: `|| unsafe {{ /* code */ }}`"
+    ),
     message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
     label = "expected an `Fn<{Args}>` closure, found `{Self}`"
 )]
@@ -139,6 +143,10 @@ pub trait Fn<Args>: FnMut<Args> {
         Args = "()",
         note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
     ),
+    on(
+        _Self = "unsafe fn",
+        note = "unsafe functions must be wrapped in closures: `|| unsafe {{ /* code */ }}`"
+    ),
     message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
     label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
 )]
@@ -211,6 +219,10 @@ pub trait FnMut<Args>: FnOnce<Args> {
         Args = "()",
         note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
     ),
+    on(
+        _Self = "unsafe fn",
+        note = "unsafe functions must be wrapped in closures: `|| unsafe {{ /* code */ }}`"
+    ),
     message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
     label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
 )]
diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
index 883348eb98c..57043c335c0 100644
--- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr
+++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
@@ -7,6 +7,7 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    |                                        required by a bound introduced by this call
    |
    = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   = note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
    |
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
index c9a20232f35..fcd668c191f 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -7,6 +7,7 @@ LL |     let x = call_it(&square, 22);
    |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
    |
@@ -22,6 +23,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
    |
@@ -37,6 +39,7 @@ LL |     let z = call_it_once(square, 22);
    |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
    |
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
index 64d57773d70..576806e3956 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -7,6 +7,7 @@ LL |     let x = call_it(&square, 22);
    |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
    |
@@ -22,6 +23,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
    |
@@ -37,6 +39,7 @@ LL |     let z = call_it_once(square, 22);
    |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20
    |