Skip to content

Commit 2b262cf

Browse files
authored
Auto merge of #37389 - cramertj:cramertj/fn-item-to-unsafe-ptr, r=eddyb
rustc_typeck: Allow reification from fn item to unsafe ptr See rust-lang/rfcs#1762. I've never contributed to the compiler internals before-- apologies if I'm not going about this the right way.
2 parents 69d364b + ab6119a commit 2b262cf

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

src/librustc_typeck/check/coercion.rs

+23-12
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
196196
// Function items are coercible to any closure
197197
// type; function pointers are not (that would
198198
// require double indirection).
199+
// Additionally, we permit coercion of function
200+
// items to drop the unsafe qualifier.
199201
self.coerce_from_fn_item(a, a_f, b)
200202
}
201203
ty::TyFnPtr(a_f) => {
@@ -504,6 +506,24 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
504506
Ok((target, AdjustDerefRef(adjustment)))
505507
}
506508

509+
fn coerce_from_safe_fn(&self,
510+
a: Ty<'tcx>,
511+
fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
512+
b: Ty<'tcx>)
513+
-> CoerceResult<'tcx> {
514+
if let ty::TyFnPtr(fn_ty_b) = b.sty {
515+
match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
516+
(hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
517+
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
518+
return self.unify_and_identity(unsafe_a, b)
519+
.map(|(ty, _)| (ty, AdjustUnsafeFnPointer));
520+
}
521+
_ => {}
522+
}
523+
}
524+
self.unify_and_identity(a, b)
525+
}
526+
507527
fn coerce_from_fn_pointer(&self,
508528
a: Ty<'tcx>,
509529
fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
@@ -516,17 +536,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
516536
let b = self.shallow_resolve(b);
517537
debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
518538

519-
if let ty::TyFnPtr(fn_ty_b) = b.sty {
520-
match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
521-
(hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
522-
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
523-
return self.unify_and_identity(unsafe_a, b)
524-
.map(|(ty, _)| (ty, AdjustUnsafeFnPointer));
525-
}
526-
_ => {}
527-
}
528-
}
529-
self.unify_and_identity(a, b)
539+
self.coerce_from_safe_fn(a, fn_ty_a, b)
530540
}
531541

532542
fn coerce_from_fn_item(&self,
@@ -544,7 +554,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
544554
match b.sty {
545555
ty::TyFnPtr(_) => {
546556
let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
547-
self.unify_and_identity(a_fn_pointer, b).map(|(ty, _)| (ty, AdjustReifyFnPointer))
557+
self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b)
558+
.map(|(ty, _)| (ty, AdjustReifyFnPointer))
548559
}
549560
_ => self.unify_and_identity(a, b),
550561
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This tests reification from safe function to `unsafe fn` pointer
12+
13+
fn do_nothing() -> () {}
14+
15+
unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () {
16+
func()
17+
}
18+
19+
pub fn main() {
20+
unsafe { call_unsafe(do_nothing); }
21+
}

0 commit comments

Comments
 (0)