Skip to content

Commit

Permalink
Rollup merge of rust-lang#64104 - Mark-Simulacrum:intrinsic-fn-ptr-ic…
Browse files Browse the repository at this point in the history
…e, 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 rust-lang#15694
  • Loading branch information
Centril authored Sep 3, 2019
2 parents 3e427d9 + dd323f8 commit 0de3668
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,9 @@ impl<'tcx> ObligationCause<'tcx> {
TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
Error0644("closure/generator type that references itself")
}
TypeError::IntrinsicCast => {
Error0308("cannot coerce intrinsics to function pointers")
}
_ => Error0308("mismatched types"),
},
}
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub enum TypeError<'tcx> {
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),

ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),

IntrinsicCast,
}

#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
Expand Down Expand Up @@ -179,6 +181,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
ConstMismatch(ref values) => {
write!(f, "expected `{}`, found `{}`", values.expected, values.found)
}
IntrinsicCast => {
write!(f, "cannot coerce intrinsics to function pointers")
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
Sorts(ref x) => return tcx.lift(x).map(Sorts),
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
IntrinsicCast => IntrinsicCast,
})
}
}
Expand Down Expand Up @@ -1338,6 +1339,7 @@ EnumTypeFoldableImpl! {
(ty::error::TypeError::Sorts)(x),
(ty::error::TypeError::ExistentialMismatch)(x),
(ty::error::TypeError::ConstMismatch)(x),
(ty::error::TypeError::IntrinsicCast),
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/librustc_typeck/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use rustc::ty::{self, Ty, TypeFoldable, TypeAndMut};
use rustc::ty::subst::SubstsRef;
use rustc::ty::adjustment::AllowTwoPhase;
use rustc::ty::cast::{CastKind, CastTy};
use rustc::ty::error::TypeError;
use rustc::middle::lang_items;
use syntax::ast;
use syntax_pos::Span;
Expand Down Expand Up @@ -461,6 +462,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
self.expr_ty,
fcx.tcx.mk_fn_ptr(f),
AllowTwoPhase::No);
if let Err(TypeError::IntrinsicCast) = res {
return Err(CastError::IllegalCast);
}
if res.is_err() {
return Err(CastError::NonScalar);
}
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ use std::ops::Deref;
use syntax::feature_gate;
use syntax::symbol::sym;
use syntax_pos;
use rustc_target::spec::abi::Abi;

struct Coerce<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
Expand Down Expand Up @@ -689,6 +690,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
match b.sty {
ty::FnPtr(_) => {
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 } =
self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);

Expand Down
15 changes: 15 additions & 0 deletions src/test/ui/reify-intrinsic.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 22 additions & 0 deletions src/test/ui/reify-intrinsic.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 0de3668

Please sign in to comment.