about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-09-03 14:27:05 +0200
committerGitHub <noreply@github.com>2019-09-03 14:27:05 +0200
commit24e3b1d0d3cfb5fddc91105bb261413566e8b701 (patch)
treea5ebb43454b05a252c93cd59c2ceacc7fd4ec32e
parenta906a83d986f73ae92c63ecfe230b14a11eed82f (diff)
parentdd323f8a72327aba0b4771ea08a8b007bba995ca (diff)
downloadrust-24e3b1d0d3cfb5fddc91105bb261413566e8b701.tar.gz
rust-24e3b1d0d3cfb5fddc91105bb261413566e8b701.zip
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
-rw-r--r--src/librustc/infer/error_reporting/mod.rs3
-rw-r--r--src/librustc/ty/error.rs5
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc_typeck/check/cast.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs6
-rw-r--r--src/test/ui/reify-intrinsic.rs15
-rw-r--r--src/test/ui/reify-intrinsic.stderr22
7 files changed, 57 insertions, 0 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 9be73cf3c6d..e684ccfeeb7 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -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"),
             },
         }
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index c70006b68d6..fe8f94ab1d3 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -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)]
@@ -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")
+            }
         }
     }
 }
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 649a5244728..ec7cf1a13c5 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -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,
         })
     }
 }
@@ -1338,6 +1339,7 @@ EnumTypeFoldableImpl! {
         (ty::error::TypeError::Sorts)(x),
         (ty::error::TypeError::ExistentialMismatch)(x),
         (ty::error::TypeError::ConstMismatch)(x),
+        (ty::error::TypeError::IntrinsicCast),
     }
 }
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 55e7a10f1aa..c216cc92b1e 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -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;
@@ -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);
                     }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 61b9c2a15ba..f2e1a6e29d6 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -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>,
@@ -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);
 
diff --git a/src/test/ui/reify-intrinsic.rs b/src/test/ui/reify-intrinsic.rs
new file mode 100644
index 00000000000..09baa059e55
--- /dev/null
+++ b/src/test/ui/reify-intrinsic.rs
@@ -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() {}
diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr
new file mode 100644
index 00000000000..4a1bd77cf7e
--- /dev/null
+++ b/src/test/ui/reify-intrinsic.stderr
@@ -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`.