about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-10-19 11:03:30 +0800
committerkennytm <kennytm@gmail.com>2018-10-19 16:47:42 +0800
commit89ebc6ce4f7bcec8e0cdffe95bf8a92bbdfe04e5 (patch)
tree801b6b3e00d6634fdd25ed26d56dc09c5c230699
parent1419a697e3849cf929b70c4d2b61643190030981 (diff)
parent38f3ad41c0bbf6ed7c389a070afb60a465b3afe3 (diff)
downloadrust-89ebc6ce4f7bcec8e0cdffe95bf8a92bbdfe04e5.tar.gz
rust-89ebc6ce4f7bcec8e0cdffe95bf8a92bbdfe04e5.zip
Rollup merge of #55071 - oli-obk:const_cast_🍨, r=RalfJung
Fix ICE and report a human readable error

fixes #55063

r? @RalfJung
-rw-r--r--src/librustc/ty/cast.rs2
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs19
-rw-r--r--src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs5
-rw-r--r--src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr10
-rw-r--r--src/test/ui/consts/min_const_fn/cast_errors.rs14
-rw-r--r--src/test/ui/consts/min_const_fn/cast_errors.stderr32
6 files changed, 79 insertions, 3 deletions
diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs
index c0861abb774..ab82f28c8bf 100644
--- a/src/librustc/ty/cast.rs
+++ b/src/librustc/ty/cast.rs
@@ -58,6 +58,8 @@ pub enum CastKind {
 }
 
 impl<'tcx> CastTy<'tcx> {
+    /// Returns `Some` for integral/pointer casts.
+    /// casts like unsizing casts will return `None`
     pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
         match t.sty {
             ty::Bool => Some(CastTy::Int(IntTy::Bool)),
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index aa559c96ec6..52c557b83d5 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -148,7 +148,7 @@ fn check_rvalue(
         Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
             check_place(tcx, mir, place, span, PlaceMode::Read)
         }
-        Rvalue::Cast(_, operand, cast_ty) => {
+        Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
             use rustc::ty::cast::CastTy;
             let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast");
             let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
@@ -163,6 +163,16 @@ fn check_rvalue(
                 _ => check_operand(tcx, mir, operand, span),
             }
         }
+        Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
+        Rvalue::Cast(CastKind::ClosureFnPointer, _, _) |
+        Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((
+            span,
+            "function pointer casts are not allowed in const fn".into(),
+        )),
+        Rvalue::Cast(CastKind::Unsize, _, _) => Err((
+            span,
+            "unsizing casts are not allowed in const fn".into(),
+        )),
         // binops are fine on integers
         Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
             check_operand(tcx, mir, lhs, span)?;
@@ -177,8 +187,11 @@ fn check_rvalue(
                 ))
             }
         }
-        // checked by regular const fn checks
-        Rvalue::NullaryOp(..) => Ok(()),
+        Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()),
+        Rvalue::NullaryOp(NullOp::Box, _) => Err((
+            span,
+            "heap allocations are not allowed in const fn".into(),
+        )),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(mir, tcx);
             if ty.is_integral() || ty.is_bool() {
diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
new file mode 100644
index 00000000000..3e42cb8c1b0
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
@@ -0,0 +1,5 @@
+const fn foo(a: i32) -> Vec<i32> {
+    vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
new file mode 100644
index 00000000000..f6b704370b6
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
@@ -0,0 +1,10 @@
+error: heap allocations are not allowed in const fn
+  --> $DIR/bad_const_fn_body_ice.rs:2:5
+   |
+LL |     vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn
+   |     ^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs
new file mode 100644
index 00000000000..8648cd35387
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cast_errors.rs
@@ -0,0 +1,14 @@
+fn main() {}
+
+const fn unsize(x: &[u8; 3]) -> &[u8] { x }
+//~^ ERROR unsizing casts are not allowed in const fn
+const fn closure() -> fn() { || {} }
+//~^ ERROR function pointers in const fn are unstable
+const fn closure2() {
+    (|| {}) as fn();
+//~^ ERROR function pointers in const fn are unstable
+}
+const fn reify(f: fn()) -> unsafe fn() { f }
+//~^ ERROR function pointers in const fn are unstable
+const fn reify2() { main as unsafe fn(); }
+//~^ ERROR function pointers in const fn are unstable
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr
new file mode 100644
index 00000000000..ba980b7aacb
--- /dev/null
+++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr
@@ -0,0 +1,32 @@
+error: unsizing casts are not allowed in const fn
+  --> $DIR/cast_errors.rs:3:41
+   |
+LL | const fn unsize(x: &[u8; 3]) -> &[u8] { x }
+   |                                         ^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:5:23
+   |
+LL | const fn closure() -> fn() { || {} }
+   |                       ^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:8:5
+   |
+LL |     (|| {}) as fn();
+   |     ^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:11:28
+   |
+LL | const fn reify(f: fn()) -> unsafe fn() { f }
+   |                            ^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+  --> $DIR/cast_errors.rs:13:21
+   |
+LL | const fn reify2() { main as unsafe fn(); }
+   |                     ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+