Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/librustc/ty/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down
22 changes: 19 additions & 3 deletions src/librustc_mir/transform/qualify_min_const_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -163,6 +163,19 @@ fn check_rvalue(
_ => check_operand(tcx, mir, operand, span),
}
}
Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((
span,
"function pointer casts are not allowed in const fn".into(),
)),
Rvalue::Cast(CastKind::ClosureFnPointer, _, _) => Err((
span,
"closures are not allowed in const fn".into(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not just having a closure, but then casting it to fn() (I think). The message should contain the word "cast" one way or another.

I would have just grouped it with the other two fn ptr casts.

)),
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)?;
Expand All @@ -177,8 +190,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() {
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs
Original file line number Diff line number Diff line change
@@ -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() {}
10 changes: 10 additions & 0 deletions src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
Original file line number Diff line number Diff line change
@@ -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