mirror of https://github.com/rust-lang/rust.git
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:
commit
2b262cf111
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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); }
|
||||||
|
}
|
Loading…
Reference in New Issue