Skip to content

Commit bec8dbd

Browse files
committed
diagnostics: give a special note for unsafe fn / Fn/FnOnce/FnMut
Fixes #90073
1 parent 60e50fc commit bec8dbd

File tree

5 files changed

+28
-0
lines changed

5 files changed

+28
-0
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs

+9
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
208208
flags.push((sym::_Self, Some("&[]".to_owned())));
209209
}
210210

211+
if self_ty.is_fn() {
212+
let fn_sig = self_ty.fn_sig(self.tcx);
213+
let shortname = match fn_sig.unsafety() {
214+
hir::Unsafety::Normal => "fn",
215+
hir::Unsafety::Unsafe => "unsafe fn",
216+
};
217+
flags.push((sym::_Self, Some(shortname.to_owned())));
218+
}
219+
211220
if let ty::Array(aty, len) = self_ty.kind() {
212221
flags.push((sym::_Self, Some("[]".to_owned())));
213222
flags.push((sym::_Self, Some(format!("[{}]", aty))));

library/core/src/ops/function.rs

+12
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959
Args = "()",
6060
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
6161
),
62+
on(
63+
_Self = "unsafe fn",
64+
note = "unsafe functions must be wrapped in closures: `|| unsafe {{ /* code */ }}`"
65+
),
6266
message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
6367
label = "expected an `Fn<{Args}>` closure, found `{Self}`"
6468
)]
@@ -139,6 +143,10 @@ pub trait Fn<Args>: FnMut<Args> {
139143
Args = "()",
140144
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
141145
),
146+
on(
147+
_Self = "unsafe fn",
148+
note = "unsafe functions must be wrapped in closures: `|| unsafe {{ /* code */ }}`"
149+
),
142150
message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
143151
label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
144152
)]
@@ -211,6 +219,10 @@ pub trait FnMut<Args>: FnOnce<Args> {
211219
Args = "()",
212220
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
213221
),
222+
on(
223+
_Self = "unsafe fn",
224+
note = "unsafe functions must be wrapped in closures: `|| unsafe {{ /* code */ }}`"
225+
),
214226
message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
215227
label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
216228
)]

src/test/ui/closures/coerce-unsafe-to-closure.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
77
| required by a bound introduced by this call
88
|
99
= help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
10+
= note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
1011
note: required by a bound in `Option::<T>::map`
1112
--> $SRC_DIR/core/src/option.rs:LL:COL
1213
|

src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ LL | let x = call_it(&square, 22);
77
| required by a bound introduced by this call
88
|
99
= help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
10+
= note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
1011
note: required by a bound in `call_it`
1112
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
1213
|
@@ -22,6 +23,7 @@ LL | let y = call_it_mut(&mut square, 22);
2223
| required by a bound introduced by this call
2324
|
2425
= help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
26+
= note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
2527
note: required by a bound in `call_it_mut`
2628
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
2729
|
@@ -37,6 +39,7 @@ LL | let z = call_it_once(square, 22);
3739
| required by a bound introduced by this call
3840
|
3941
= help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
42+
= note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
4043
note: required by a bound in `call_it_once`
4144
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
4245
|

src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ LL | let x = call_it(&square, 22);
77
| required by a bound introduced by this call
88
|
99
= help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
10+
= note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
1011
note: required by a bound in `call_it`
1112
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
1213
|
@@ -22,6 +23,7 @@ LL | let y = call_it_mut(&mut square, 22);
2223
| required by a bound introduced by this call
2324
|
2425
= help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
26+
= note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
2527
note: required by a bound in `call_it_mut`
2628
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
2729
|
@@ -37,6 +39,7 @@ LL | let z = call_it_once(square, 22);
3739
| required by a bound introduced by this call
3840
|
3941
= help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
42+
= note: unsafe functions must be wrapped in closures: `|| unsafe { /* code */ }`
4043
note: required by a bound in `call_it_once`
4144
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20
4245
|

0 commit comments

Comments
 (0)