Rollup merge of #64104 - Mark-Simulacrum:intrinsic-fn-ptr-ice, r=estebank
Emit error on intrinsic to fn ptr casts I'm not sure if a type error is the best way of doing this but it seemed like a relatively correct place to do it, and I expect this is a pretty rare case to hit anyway. Fixes #15694
This commit is contained in:
commit
24e3b1d0d3
@ -1636,6 +1636,9 @@ fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
|
|||||||
TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
|
TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
|
||||||
Error0644("closure/generator type that references itself")
|
Error0644("closure/generator type that references itself")
|
||||||
}
|
}
|
||||||
|
TypeError::IntrinsicCast => {
|
||||||
|
Error0308("cannot coerce intrinsics to function pointers")
|
||||||
|
}
|
||||||
_ => Error0308("mismatched types"),
|
_ => Error0308("mismatched types"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,8 @@ pub enum TypeError<'tcx> {
|
|||||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
||||||
|
|
||||||
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
|
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
|
||||||
|
|
||||||
|
IntrinsicCast,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
|
||||||
@ -179,6 +181,9 @@ macro_rules! pluralise {
|
|||||||
ConstMismatch(ref values) => {
|
ConstMismatch(ref values) => {
|
||||||
write!(f, "expected `{}`, found `{}`", values.expected, values.found)
|
write!(f, "expected `{}`, found `{}`", values.expected, values.found)
|
||||||
}
|
}
|
||||||
|
IntrinsicCast => {
|
||||||
|
write!(f, "cannot coerce intrinsics to function pointers")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,6 +748,7 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
|||||||
Sorts(ref x) => return tcx.lift(x).map(Sorts),
|
Sorts(ref x) => return tcx.lift(x).map(Sorts),
|
||||||
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
|
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
|
||||||
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
|
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
|
||||||
|
IntrinsicCast => IntrinsicCast,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1338,6 +1339,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> {
|
|||||||
(ty::error::TypeError::Sorts)(x),
|
(ty::error::TypeError::Sorts)(x),
|
||||||
(ty::error::TypeError::ExistentialMismatch)(x),
|
(ty::error::TypeError::ExistentialMismatch)(x),
|
||||||
(ty::error::TypeError::ConstMismatch)(x),
|
(ty::error::TypeError::ConstMismatch)(x),
|
||||||
|
(ty::error::TypeError::IntrinsicCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
use rustc::ty::subst::SubstsRef;
|
use rustc::ty::subst::SubstsRef;
|
||||||
use rustc::ty::adjustment::AllowTwoPhase;
|
use rustc::ty::adjustment::AllowTwoPhase;
|
||||||
use rustc::ty::cast::{CastKind, CastTy};
|
use rustc::ty::cast::{CastKind, CastTy};
|
||||||
|
use rustc::ty::error::TypeError;
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
@ -461,6 +462,9 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
|
|||||||
self.expr_ty,
|
self.expr_ty,
|
||||||
fcx.tcx.mk_fn_ptr(f),
|
fcx.tcx.mk_fn_ptr(f),
|
||||||
AllowTwoPhase::No);
|
AllowTwoPhase::No);
|
||||||
|
if let Err(TypeError::IntrinsicCast) = res {
|
||||||
|
return Err(CastError::IllegalCast);
|
||||||
|
}
|
||||||
if res.is_err() {
|
if res.is_err() {
|
||||||
return Err(CastError::NonScalar);
|
return Err(CastError::NonScalar);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
use syntax::feature_gate;
|
use syntax::feature_gate;
|
||||||
use syntax::symbol::sym;
|
use syntax::symbol::sym;
|
||||||
use syntax_pos;
|
use syntax_pos;
|
||||||
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
struct Coerce<'a, 'tcx> {
|
struct Coerce<'a, 'tcx> {
|
||||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||||
@ -689,6 +690,11 @@ fn coerce_from_fn_item(&self,
|
|||||||
match b.sty {
|
match b.sty {
|
||||||
ty::FnPtr(_) => {
|
ty::FnPtr(_) => {
|
||||||
let a_sig = a.fn_sig(self.tcx);
|
let a_sig = a.fn_sig(self.tcx);
|
||||||
|
// Intrinsics are not coercible to function pointers
|
||||||
|
if a_sig.abi() == Abi::RustIntrinsic ||
|
||||||
|
a_sig.abi() == Abi::PlatformIntrinsic {
|
||||||
|
return Err(TypeError::IntrinsicCast);
|
||||||
|
}
|
||||||
let InferOk { value: a_sig, mut obligations } =
|
let InferOk { value: a_sig, mut obligations } =
|
||||||
self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
|
self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
|
||||||
|
|
||||||
|
15
src/test/ui/reify-intrinsic.rs
Normal file
15
src/test/ui/reify-intrinsic.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// check-fail
|
||||||
|
|
||||||
|
#![feature(intrinsics)]
|
||||||
|
|
||||||
|
fn a() {
|
||||||
|
let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
|
||||||
|
//~^ ERROR cannot coerce
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() {
|
||||||
|
let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
|
||||||
|
//~^ ERROR casting
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
22
src/test/ui/reify-intrinsic.stderr
Normal file
22
src/test/ui/reify-intrinsic.stderr
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
error[E0308]: cannot coerce intrinsics to function pointers
|
||||||
|
--> $DIR/reify-intrinsic.rs:6:64
|
||||||
|
|
|
||||||
|
LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| cannot coerce intrinsics to function pointers
|
||||||
|
| help: use parentheses to call this function: `std::mem::transmute(...)`
|
||||||
|
|
|
||||||
|
= note: expected type `unsafe extern "rust-intrinsic" fn(isize) -> usize`
|
||||||
|
found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
|
||||||
|
|
||||||
|
error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
|
||||||
|
--> $DIR/reify-intrinsic.rs:11:13
|
||||||
|
|
|
||||||
|
LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0308, E0606.
|
||||||
|
For more information about an error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user