Skip to content

Commit 270bf4c

Browse files
committed
Add example of reifyfnpointer with const drop
1 parent d72e63b commit 270bf4c

File tree

11 files changed

+99
-29
lines changed

11 files changed

+99
-29
lines changed

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -184,25 +184,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
184184
let cast = bx.cx().layout_of(self.monomorphize(&mir_cast_ty));
185185

186186
let val = match *kind {
187-
mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => {
188-
match *operand.layout.ty.kind() {
189-
ty::FnDef(def_id, substs) => {
190-
if bx.cx().tcx().has_attr(def_id, sym::rustc_args_required_const) {
191-
bug!("reifying a fn ptr that requires const arguments");
192-
}
193-
let instance = ty::Instance::resolve_for_fn_ptr(
194-
bx.tcx(),
195-
ty::ParamEnv::reveal_all(),
196-
def_id,
197-
substs,
198-
)
199-
.unwrap()
200-
.polymorphize(bx.cx().tcx());
201-
OperandValue::Immediate(bx.get_fn_addr(instance))
187+
mir::CastKind::Pointer(
188+
PointerCast::ReifyFnPointer | PointerCast::ReifyNotConstFnPointer,
189+
) => match operand.layout.ty.kind() {
190+
ty::FnDef(def_id, substs) => {
191+
if bx.cx().tcx().has_attr(def_id, sym::rustc_args_required_const) {
192+
bug!("reifying a fn ptr that requires const arguments");
202193
}
203-
_ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty),
194+
let instance = ty::Instance::resolve_for_fn_ptr(
195+
bx.tcx(),
196+
ty::ParamEnv::reveal_all(),
197+
def_id,
198+
substs,
199+
)
200+
.unwrap()
201+
.polymorphize(bx.cx().tcx());
202+
OperandValue::Immediate(bx.get_fn_addr(instance))
204203
}
205-
}
204+
_ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty),
205+
},
206206
mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)) => {
207207
match *operand.layout.ty.kind() {
208208
ty::Closure(def_id, substs) => {

compiler/rustc_lint/src/builtin.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2807,8 +2807,8 @@ impl ClashingExternDeclarations {
28072807
let a_sig = a_poly_sig.skip_binder();
28082808
let b_sig = b_poly_sig.skip_binder();
28092809

2810-
(a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
2811-
== (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
2810+
(a_sig.abi, a_sig.unsafety, a_sig.c_variadic, a_sig.constness)
2811+
== (b_sig.abi, b_sig.unsafety, b_sig.c_variadic, b_sig.constness)
28122812
&& a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
28132813
structurally_same_type_impl(seen_types, cx, a, b, ckind)
28142814
})

compiler/rustc_middle/src/ty/adjustment.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ pub enum PointerCast {
1111
/// Go from a fn-item type to a fn-pointer type.
1212
ReifyFnPointer,
1313

14+
/// Go from a fn-item type to a not const fn-pointer type (drop const qualifier)
15+
ReifyNotConstFnPointer,
16+
1417
/// Go from a safe fn pointer to an unsafe fn pointer.
1518
UnsafeFnPointer,
1619

compiler/rustc_middle/src/ty/context.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,6 +2110,10 @@ impl<'tcx> TyCtxt<'tcx> {
21102110
})
21112111
}
21122112

2113+
pub fn signature_not_const_fn(self, sig: PolyFnSig<'tcx>) -> PolyFnSig<'tcx> {
2114+
sig.map_bound(|s| ty::FnSig { constness: hir::Constness::NotConst, ..s })
2115+
}
2116+
21132117
/// Same a `self.mk_region(kind)`, but avoids accessing the interners if
21142118
/// `*r == kind`.
21152119
#[inline]
@@ -2302,6 +2306,13 @@ impl<'tcx> TyCtxt<'tcx> {
23022306
self.mk_ty(FnPtr(fty))
23032307
}
23042308

2309+
#[inline]
2310+
pub fn mk_not_const_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
2311+
let mut not_const = fty.skip_binder();
2312+
not_const.constness = hir::Constness::NotConst;
2313+
self.mk_ty(FnPtr(ty::Binder::dummy(not_const)))
2314+
}
2315+
23052316
#[inline]
23062317
pub fn mk_dynamic(
23072318
self,

compiler/rustc_mir/src/borrow_check/type_check/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,35 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20722072
}
20732073
}
20742074

2075+
CastKind::Pointer(PointerCast::ReifyNotConstFnPointer) => {
2076+
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
2077+
2078+
// The type that we see in the fcx is like
2079+
// `foo::<'a, 'b>`, where `foo` is the path to a
2080+
// function definition. When we extract the
2081+
// signature, it comes from the `fn_sig` query,
2082+
// and hence may contain unnormalized results.
2083+
let fn_sig = self.normalize(fn_sig, location);
2084+
2085+
let ty_fn_ptr_from = tcx.mk_not_const_fn_ptr(fn_sig);
2086+
2087+
if let Err(terr) = self.eq_types(
2088+
ty_fn_ptr_from,
2089+
ty,
2090+
location.to_locations(),
2091+
ConstraintCategory::Cast,
2092+
) {
2093+
span_mirbug!(
2094+
self,
2095+
rvalue,
2096+
"equating {:?} with {:?} yields {:?}",
2097+
ty_fn_ptr_from,
2098+
ty,
2099+
terr
2100+
);
2101+
}
2102+
}
2103+
20752104
CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
20762105
let sig = match op.ty(body, tcx).kind() {
20772106
ty::Closure(_, substs) => substs.as_closure().sig(),

compiler/rustc_mir/src/interpret/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
4545
self.write_immediate(*v, dest)?;
4646
}
4747

48-
Pointer(PointerCast::ReifyFnPointer) => {
48+
Pointer(PointerCast::ReifyFnPointer | PointerCast::ReifyNotConstFnPointer) => {
4949
// The src operand does not matter, just its type
5050
match *src.layout.ty.kind() {
5151
ty::FnDef(def_id, substs) => {

compiler/rustc_mir/src/transform/check_consts/validation.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -748,8 +748,9 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
748748
ty::FnPtr(fn_sig) => {
749749
// At this point, we are calling a function by raw pointer because
750750
// we know that it is const
751-
if self.ccx.tcx.features().const_fn_pointer &&
752-
fn_sig.constness() == hir::Constness::Const {
751+
if self.ccx.tcx.features().const_fn_pointer
752+
&& fn_sig.constness() == hir::Constness::Const
753+
{
753754
return;
754755
}
755756
self.check_op(ops::FnCallIndirect);

compiler/rustc_typeck/src/check/coercion.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
952952
{
953953
let prev_ty = self.resolve_vars_with_obligations(prev_ty);
954954
let new_ty = self.resolve_vars_with_obligations(new_ty);
955+
let mut prev_drop_const = false;
956+
let mut new_drop_const = false;
955957
debug!(
956958
"coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)",
957959
prev_ty,
@@ -982,7 +984,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
982984
// We have a LUB of prev_ty and new_ty, just return it.
983985
Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)),
984986
Err(_) => {
985-
(Some(prev_ty.fn_sig(self.tcx)), Some(new_ty.fn_sig(self.tcx)))
987+
let mut prev_sig = prev_ty.fn_sig(self.tcx);
988+
let mut new_sig = new_ty.fn_sig(self.tcx);
989+
if prev_sig.constness() != new_sig.constness() {
990+
if prev_sig.constness() == hir::Constness::Const {
991+
prev_sig = self.tcx.signature_not_const_fn(prev_sig);
992+
prev_drop_const = true;
993+
} else {
994+
new_sig = self.tcx.signature_not_const_fn(prev_sig);
995+
new_drop_const = true;
996+
}
997+
}
998+
(Some(prev_sig), Some(new_sig))
986999
}
9871000
}
9881001
}
@@ -1028,12 +1041,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10281041
let fn_ptr = self.tcx.mk_fn_ptr(sig);
10291042
let prev_adjustment = match prev_ty.kind() {
10301043
ty::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(a_sig.unsafety())),
1031-
ty::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
1044+
ty::FnDef(..) => {
1045+
if prev_drop_const {
1046+
Adjust::Pointer(PointerCast::ReifyNotConstFnPointer)
1047+
} else {
1048+
Adjust::Pointer(PointerCast::ReifyFnPointer)
1049+
}
1050+
}
10321051
_ => unreachable!(),
10331052
};
10341053
let next_adjustment = match new_ty.kind() {
10351054
ty::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(b_sig.unsafety())),
1036-
ty::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
1055+
ty::FnDef(..) => {
1056+
if new_drop_const {
1057+
Adjust::Pointer(PointerCast::ReifyNotConstFnPointer)
1058+
} else {
1059+
Adjust::Pointer(PointerCast::ReifyFnPointer)
1060+
}
1061+
}
10371062
_ => unreachable!(),
10381063
};
10391064
for expr in exprs.iter().map(|e| e.as_coercion_site()) {

src/test/ui/consts/const_fn_pointer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ const fn bazz() { baz(FOO) }
1313
trait Bar { const F: const fn(Self) -> Self; }
1414

1515
const fn map_i32(x: i32) -> i32 { x * 2 }
16-
impl Bar for i32 { const F: const fn(Self) -> Self = map_i32; }
16+
impl Bar for i32 { const F: const fn(Self) -> Self = map_i32; }
1717
const fn map_u32(x: u32) -> u32 { x * 3 }
18-
impl Bar for u32 { const F: const fn(Self) -> Self = map_u32; }
18+
impl Bar for u32 { const F: const fn(Self) -> Self = map_u32; }
1919

2020
const fn map_smth<T: Bar>(v: T) -> T {
2121
<T as Bar>::F(v)
2222
}
2323

24-
fn main() {
24+
fn main() {
2525
const VAR: i32 = map_smth(2);
2626
assert_eq!(VAR, 4);
2727
}

src/test/ui/consts/const_fn_ptr_cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ const _: const unsafe fn() = unsafe_fn;
2222

2323
const _: unsafe fn() = const_unsafe_fn;
2424

25-
fn main() { }
25+
fn main() { }

src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv
152152
PointerCast::UnsafeFnPointer
153153
| PointerCast::ClosureFnPointer(_)
154154
| PointerCast::ReifyFnPointer
155+
| PointerCast::ReifyNotConstFnPointer
155156
| PointerCast::NotConstFnPointer
156157
| PointerCast::UnsafeNotConstFnPointer,
157158
),

0 commit comments

Comments
 (0)