Skip to content

Commit 8bebf82

Browse files
committed
add case for unsafe and safe fn coerce
1 parent b53da99 commit 8bebf82

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
88
use rustc_hir::def_id::DefId;
99
use rustc_hir::intravisit::VisitorExt;
1010
use rustc_hir::lang_items::LangItem;
11-
use rustc_hir::{self as hir, AmbigArg, ExprKind, GenericArg, HirId, Node, QPath, intravisit};
11+
use rustc_hir::{
12+
self as hir, AmbigArg, ExprKind, GenericArg, HirId, Node, QPath, Safety, intravisit,
13+
};
1214
use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend;
1315
use rustc_hir_analysis::hir_ty_lowering::generics::{
1416
check_generic_arg_count_for_call, lower_generic_args,
@@ -20,7 +22,9 @@ use rustc_hir_analysis::hir_ty_lowering::{
2022
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
2123
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
2224
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
23-
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
25+
use rustc_middle::ty::adjustment::{
26+
Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion,
27+
};
2428
use rustc_middle::ty::{
2529
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity,
2630
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs,
@@ -336,10 +340,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
336340
// A reborrow has no effect before a dereference, so we can safely replace adjustments.
337341
*entry.get_mut() = adj;
338342
}
343+
(
344+
&mut [
345+
Adjustment {
346+
kind:
347+
Adjust::Pointer(PointerCoercion::ClosureFnPointer(Safety::Safe)),
348+
target: intermediate_target,
349+
..
350+
},
351+
],
352+
&[
353+
Adjustment {
354+
kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer),
355+
..
356+
},
357+
],
358+
) => {
359+
// dont allow coerce `unsafe fn()` to `fn()`
360+
self.dcx()
361+
.struct_span_err(
362+
expr.span,
363+
format!(
364+
"cannot coerce between `{}` and unsafe function pointers",
365+
intermediate_target
366+
),
367+
)
368+
.emit();
369+
}
339370

340371
_ => {
341372
// FIXME: currently we never try to compose autoderefs
342-
// and ReifyFnPointer/UnsafeFnPointer, but we could.
373+
// and ReifyFnPointer, but we could.
343374
self.dcx().span_delayed_bug(
344375
expr.span,
345376
format!(
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
fn main() {
2+
// this is work
3+
match () {
4+
_ if true => || (),
5+
_ => (|| ()) as unsafe fn(),
6+
_ if true => (|| ()) as fn(),
7+
};
8+
9+
// this is not
10+
match () {
11+
_ if true => || (), //~ ERROR cannot coerce between `fn()` and unsafe function pointers
12+
_ if true => (|| ()) as fn(),
13+
_ => (|| ()) as unsafe fn(),
14+
};
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: cannot coerce between `fn()` and unsafe function pointers
2+
--> $DIR/unsafe-fn-to-fn-match-150128.rs:11:22
3+
|
4+
LL | _ if true => || (),
5+
| ^^^^^
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)