Auto merge of #37389 - cramertj:cramertj/fn-item-to-unsafe-ptr, r=eddyb

rustc_typeck: Allow reification from fn item to unsafe ptr

See https://github.com/rust-lang/rfcs/issues/1762.

I've never contributed to the compiler internals before-- apologies if I'm not going about this the right way.
This commit is contained in:
bors 2016-10-29 12:08:38 -07:00 committed by GitHub
commit 2b262cf111
2 changed files with 44 additions and 12 deletions

View File

@ -196,6 +196,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
// Function items are coercible to any closure // Function items are coercible to any closure
// type; function pointers are not (that would // type; function pointers are not (that would
// require double indirection). // require double indirection).
// Additionally, we permit coercion of function
// items to drop the unsafe qualifier.
self.coerce_from_fn_item(a, a_f, b) self.coerce_from_fn_item(a, a_f, b)
} }
ty::TyFnPtr(a_f) => { ty::TyFnPtr(a_f) => {
@ -504,6 +506,24 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
Ok((target, AdjustDerefRef(adjustment))) Ok((target, AdjustDerefRef(adjustment)))
} }
fn coerce_from_safe_fn(&self,
a: Ty<'tcx>,
fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
b: Ty<'tcx>)
-> CoerceResult<'tcx> {
if let ty::TyFnPtr(fn_ty_b) = b.sty {
match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
(hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
return self.unify_and_identity(unsafe_a, b)
.map(|(ty, _)| (ty, AdjustUnsafeFnPointer));
}
_ => {}
}
}
self.unify_and_identity(a, b)
}
fn coerce_from_fn_pointer(&self, fn coerce_from_fn_pointer(&self,
a: Ty<'tcx>, a: Ty<'tcx>,
fn_ty_a: &'tcx ty::BareFnTy<'tcx>, fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
@ -516,17 +536,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
let b = self.shallow_resolve(b); let b = self.shallow_resolve(b);
debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b); debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
if let ty::TyFnPtr(fn_ty_b) = b.sty { self.coerce_from_safe_fn(a, fn_ty_a, b)
match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
(hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
return self.unify_and_identity(unsafe_a, b)
.map(|(ty, _)| (ty, AdjustUnsafeFnPointer));
}
_ => {}
}
}
self.unify_and_identity(a, b)
} }
fn coerce_from_fn_item(&self, fn coerce_from_fn_item(&self,
@ -544,7 +554,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
match b.sty { match b.sty {
ty::TyFnPtr(_) => { ty::TyFnPtr(_) => {
let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a); let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
self.unify_and_identity(a_fn_pointer, b).map(|(ty, _)| (ty, AdjustReifyFnPointer)) self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b)
.map(|(ty, _)| (ty, AdjustReifyFnPointer))
} }
_ => self.unify_and_identity(a, b), _ => self.unify_and_identity(a, b),
} }

View File

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This tests reification from safe function to `unsafe fn` pointer
fn do_nothing() -> () {}
unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () {
func()
}
pub fn main() {
unsafe { call_unsafe(do_nothing); }
}