From 507381ed0367f27e8804a1da33f8565c96a260ce Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 13 Oct 2018 23:38:31 +0200 Subject: [PATCH] Fix ICE and report a human readable error --- src/librustc/ty/cast.rs | 2 ++ src/librustc_mir/transform/qualify_min_const_fn.rs | 13 ++++++++++--- .../ui/consts/min_const_fn/bad_const_fn_body_ice.rs | 5 +++++ .../min_const_fn/bad_const_fn_body_ice.stderr | 10 ++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs create mode 100644 src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index c0861abb774d..ab82f28c8bff 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> { 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 aa559c96ec66..edcae4648b72 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,10 @@ fn check_rvalue( _ => check_operand(tcx, mir, operand, span), } } + Rvalue::Cast(_, _, _) => Err(( + span, + "only int casts are 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 +181,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 000000000000..3e42cb8c1b07 --- /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 { + 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 000000000000..f6b704370b6f --- /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 +