From bb78426ca8f12f467e4d3bb38e82c0d3b6209e61 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 13 Aug 2018 13:48:47 +0200 Subject: [PATCH 1/2] Allow panicking with string literal messages inside constants --- src/librustc/ich/impls_ty.rs | 7 +- src/librustc/middle/lang_items.rs | 2 + src/librustc/mir/interpret/error.rs | 12 ++- src/librustc/ty/structural_impls.rs | 6 +- src/librustc_mir/interpret/const_eval.rs | 95 ++++++++++++++++--- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 26 ++++- src/libstd/panicking.rs | 1 + src/libsyntax/feature_gate.rs | 3 + src/test/ui/const-eval/const_panic.rs | 22 +++++ src/test/ui/const-eval/const_panic.stderr | 33 +++++++ src/test/ui/const-eval/const_panic_libcore.rs | 22 +++++ .../ui/const-eval/const_panic_libcore.stderr | 33 +++++++ .../ui/const-eval/const_panic_libcore_main.rs | 35 +++++++ .../const_panic_libcore_main.stderr | 33 +++++++ .../ui/const-eval/feature-gate-const_panic.rs | 20 ++++ .../feature-gate-const_panic.stderr | 30 ++++++ src/test/ui/issues/issue-32829.rs | 2 +- src/test/ui/issues/issue-32829.stderr | 5 +- 20 files changed, 366 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/const-eval/const_panic.rs create mode 100644 src/test/ui/const-eval/const_panic.stderr create mode 100644 src/test/ui/const-eval/const_panic_libcore.rs create mode 100644 src/test/ui/const-eval/const_panic_libcore.stderr create mode 100644 src/test/ui/const-eval/const_panic_libcore_main.rs create mode 100644 src/test/ui/const-eval/const_panic_libcore_main.stderr create mode 100644 src/test/ui/const-eval/feature-gate-const_panic.rs create mode 100644 src/test/ui/const-eval/feature-gate-const_panic.stderr diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 46f4ed4ec478b..54829058f44fa 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -536,7 +536,6 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> { DeallocateNonBasePtr | HeapAllocZeroBytes | Unreachable | - Panic | ReadFromReturnPointer | UnimplementedTraitSelection | TypeckError | @@ -550,6 +549,12 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> { GeneratorResumedAfterReturn | GeneratorResumedAfterPanic | InfiniteLoop => {} + Panic { ref msg, ref file, line, col } => { + msg.hash_stable(hcx, hasher); + file.hash_stable(hcx, hasher); + line.hash_stable(hcx, hasher); + col.hash_stable(hcx, hasher); + }, ReferencedConstant(ref err) => err.hash_stable(hcx, hasher), MachineError(ref err) => err.hash_stable(hcx, hasher), FunctionPointerTyMismatch(a, b) => { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index cf94a0fb4b4ba..8c300a0aba0ec 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -305,6 +305,8 @@ language_item_table! { PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn; PanicInfoLangItem, "panic_info", panic_info; PanicImplLangItem, "panic_impl", panic_impl; + // Libstd panic entry point. Necessary for const eval to be able to catch it + BeginPanicFnLangItem, "begin_panic", begin_panic_fn; ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; BoxFreeFnLangItem, "box_free", box_free_fn; diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 1e9584bc55bdf..436478b84162a 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -17,6 +17,7 @@ use errors::DiagnosticBuilder; use syntax_pos::Span; use syntax::ast; +use syntax::symbol::Symbol; pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc>>; @@ -250,7 +251,12 @@ pub enum EvalErrorKind<'tcx, O> { HeapAllocZeroBytes, HeapAllocNonPowerOfTwoAlignment(u64), Unreachable, - Panic, + Panic { + msg: Symbol, + line: u32, + col: u32, + file: Symbol, + }, ReadFromReturnPointer, PathNotFound(Vec), UnimplementedTraitSelection, @@ -370,7 +376,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { "tried to re-, de-, or allocate heap memory with alignment that is not a power of two", Unreachable => "entered unreachable code", - Panic => + Panic { .. } => "the evaluated program panicked", ReadFromReturnPointer => "tried to read from the return pointer", @@ -465,6 +471,8 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { write!(f, "{}", inner), IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()), + Panic { ref msg, line, col, ref file } => + write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col), _ => write!(f, "{}", self.description()), } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index ad29f808285b1..95e2cc6c3870d 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -574,7 +574,11 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> { HeapAllocZeroBytes => HeapAllocZeroBytes, HeapAllocNonPowerOfTwoAlignment(n) => HeapAllocNonPowerOfTwoAlignment(n), Unreachable => Unreachable, - Panic => Panic, + Panic { ref msg, ref file, line, col } => Panic { + msg: msg.clone(), + file: file.clone(), + line, col, + }, ReadFromReturnPointer => ReadFromReturnPointer, PathNotFound(ref v) => PathNotFound(v.clone()), UnimplementedTraitSelection => UnimplementedTraitSelection, diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 8aba49531239e..a306a4d7c1e1e 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -5,13 +5,14 @@ use rustc::hir; use rustc::mir::interpret::ConstEvalErr; use rustc::mir; use rustc::ty::{self, TyCtxt, Instance}; -use rustc::ty::layout::{LayoutOf, Primitive, TyLayout}; +use rustc::ty::layout::{LayoutOf, Primitive, TyLayout, Size}; use rustc::ty::subst::Subst; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax::ast::Mutability; use syntax::source_map::Span; use syntax::source_map::DUMMY_SP; +use syntax::symbol::Symbol; use rustc::mir::interpret::{ EvalResult, EvalError, EvalErrorKind, GlobalId, @@ -19,7 +20,7 @@ use rustc::mir::interpret::{ }; use super::{ Place, PlaceExtra, PlaceTy, MemPlace, OpTy, Operand, Value, - EvalContext, StackPopCleanup, Memory, MemoryKind + EvalContext, StackPopCleanup, Memory, MemoryKind, MPlaceTy, }; pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>( @@ -237,23 +238,56 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator { if !ecx.tcx.is_const_fn(instance.def_id()) { let def_id = instance.def_id(); // Some fn calls are actually BinOp intrinsics - let (op, oflo) = if let Some(op) = ecx.tcx.is_binop_lang_item(def_id) { - op + let _: ! = if let Some((op, oflo)) = ecx.tcx.is_binop_lang_item(def_id) { + let (dest, bb) = destination.expect("128 lowerings can't diverge"); + let l = ecx.read_value(args[0])?; + let r = ecx.read_value(args[1])?; + if oflo { + ecx.binop_with_overflow(op, l, r, dest)?; + } else { + ecx.binop_ignore_overflow(op, l, r, dest)?; + } + ecx.goto_block(bb); + return Ok(true); + } else if Some(def_id) == ecx.tcx.lang_items().panic_fn() { + assert!(args.len() == 1); + // &(&'static str, &'static str, u32, u32) + let ptr = ecx.read_value(args[0])?; + let place = ecx.ref_to_mplace(ptr)?; + let (msg, file, line, col) = ( + place_field(ecx, 0, place)?, + place_field(ecx, 1, place)?, + place_field(ecx, 2, place)?, + place_field(ecx, 3, place)?, + ); + + let msg = to_str(ecx, msg)?; + let file = to_str(ecx, file)?; + let line = to_u32(line)?; + let col = to_u32(col)?; + return Err(EvalErrorKind::Panic { msg, file, line, col }.into()); + } else if Some(def_id) == ecx.tcx.lang_items().begin_panic_fn() { + assert!(args.len() == 2); + // &'static str, &(&'static str, u32, u32) + let msg = ecx.read_value(args[0])?; + let ptr = ecx.read_value(args[1])?; + let place = ecx.ref_to_mplace(ptr)?; + let (file, line, col) = ( + place_field(ecx, 0, place)?, + place_field(ecx, 1, place)?, + place_field(ecx, 2, place)?, + ); + + let msg = to_str(ecx, msg.value)?; + let file = to_str(ecx, file)?; + let line = to_u32(line)?; + let col = to_u32(col)?; + return Err(EvalErrorKind::Panic { msg, file, line, col }.into()); } else { return Err( ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into(), ); }; - let (dest, bb) = destination.expect("128 lowerings can't diverge"); - let l = ecx.read_value(args[0])?; - let r = ecx.read_value(args[1])?; - if oflo { - ecx.binop_with_overflow(op, l, r, dest)?; - } else { - ecx.binop_ignore_overflow(op, l, r, dest)?; - } - ecx.goto_block(bb); - return Ok(true); } let mir = match ecx.load_mir(instance.def) { Ok(mir) => mir, @@ -412,6 +446,39 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator { } } +fn place_field<'a, 'tcx, 'mir>( + ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, + i: u64, + place: MPlaceTy<'tcx>, +) -> EvalResult<'tcx, Value> { + let place = ecx.mplace_field(place, i)?; + Ok(ecx.try_read_value_from_mplace(place)?.expect("bad panic arg layout")) +} + +fn to_str<'a, 'tcx, 'mir>( + ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, + val: Value, +) -> EvalResult<'tcx, Symbol> { + if let Value::ScalarPair(ptr, len) = val { + let len = len.not_undef()?.to_bits(ecx.memory.pointer_size())?; + let bytes = ecx.memory.read_bytes(ptr.not_undef()?, Size::from_bytes(len as u64))?; + let str = ::std::str::from_utf8(bytes).map_err(|err| EvalErrorKind::ValidationFailure(err.to_string()))?; + Ok(Symbol::intern(str)) + } else { + bug!("panic arg is not a str") + } +} + +fn to_u32<'a, 'tcx, 'mir>( + val: Value, +) -> EvalResult<'tcx, u32> { + if let Value::Scalar(n) = val { + Ok(n.not_undef()?.to_bits(Size::from_bits(32))? as u32) + } else { + bug!("panic arg is not a str") + } +} + /// Project to a field of a (variant of a) const pub fn const_field<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index df3dc44b22984..d9e7f33e836f5 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -213,7 +213,7 @@ fn from_known_layout<'tcx>( impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { /// Try reading a value in memory; this is interesting particularily for ScalarPair. /// Return None if the layout does not permit loading this as a value. - fn try_read_value_from_mplace( + pub(super) fn try_read_value_from_mplace( &self, mplace: MPlaceTy<'tcx>, ) -> EvalResult<'tcx, Option> { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 3f77e69b7dcbe..fa11e6f0719b1 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -230,7 +230,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { // FIXME: implement => {}, - | Panic + | Panic { .. } | BoundsCheck{..} | Overflow(_) | OverflowNeg diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index d876ee77e76cf..20525b5f484ba 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -400,6 +400,11 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { (self.qualif, Lrc::new(promoted_temps)) } + + fn is_const_panic_fn(&self, def_id: DefId) -> bool { + Some(def_id) == self.tcx.lang_items().panic_fn() || + Some(def_id) == self.tcx.lang_items().begin_panic_fn() + } } /// Accumulates an Rvalue or Call's effects in self.qualif. @@ -834,7 +839,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } _ => { - if self.tcx.is_const_fn(def_id) { + if self.tcx.is_const_fn(def_id) || self.is_const_panic_fn(def_id) { is_const_fn = Some(def_id); } } @@ -880,8 +885,25 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Const fn calls. if let Some(def_id) = is_const_fn { + // check the const_panic feature gate or // find corresponding rustc_const_unstable feature - if let Some(&attr::Stability { + // FIXME: cannot allow this inside `allow_internal_unstable` because that would make + // `panic!` insta stable in constants, since the macro is marked with the attr + if self.is_const_panic_fn(def_id) { + if self.mode == Mode::Fn { + // never promote panics + self.qualif = Qualif::NOT_CONST; + } else if !self.tcx.sess.features_untracked().const_panic { + // don't allow panics in constants without the feature gate + emit_feature_err( + &self.tcx.sess.parse_sess, + "const_panic", + self.span, + GateIssue::Language, + &format!("panicking in {}s is unstable", self.mode), + ); + } + } else if let Some(&attr::Stability { rustc_const_unstable: Some(attr::RustcConstUnstable { feature: ref feature_name }), diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 283fd36af41ff..862f0fd71b0a3 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -397,6 +397,7 @@ fn continue_panic_fmt(info: &PanicInfo) -> ! { #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "0")] +#[cfg_attr(not(any(stage0, test)), lang = "begin_panic")] #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! { // Note that this should be the only allocation performed in this code path. diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 71ad118ed8eac..4a819814d815c 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -224,6 +224,9 @@ declare_features! ( // Allows comparing raw pointers during const eval (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), + // Allows panicking during const eval (produces compile-time errors) + (active, const_panic, "1.29.0", Some(51999), None), + // Allows using #[prelude_import] on glob `use` items. // // rustc internal diff --git a/src/test/ui/const-eval/const_panic.rs b/src/test/ui/const-eval/const_panic.rs new file mode 100644 index 0000000000000..f2170f509eb30 --- /dev/null +++ b/src/test/ui/const-eval/const_panic.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_panic)] + +fn main() {} + +const Z: () = panic!("cheese"); +//~^ ERROR this constant cannot be used + +const Y: () = unreachable!(); +//~^ ERROR this constant cannot be used + +const X: () = unimplemented!(); +//~^ ERROR this constant cannot be used diff --git a/src/test/ui/const-eval/const_panic.stderr b/src/test/ui/const-eval/const_panic.stderr new file mode 100644 index 0000000000000..c11146f4882c2 --- /dev/null +++ b/src/test/ui/const-eval/const_panic.stderr @@ -0,0 +1,33 @@ +error: this constant cannot be used + --> $DIR/const_panic.rs:15:1 + | +LL | const Z: () = panic!("cheese"); + | ^^^^^^^^^^^^^^----------------^ + | | + | the evaluated program panicked at 'cheese', $DIR/const_panic.rs:15:15 + | + = note: #[deny(const_err)] on by default + = 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: this constant cannot be used + --> $DIR/const_panic.rs:18:1 + | +LL | const Y: () = unreachable!(); + | ^^^^^^^^^^^^^^--------------^ + | | + | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:18:15 + | + = 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: this constant cannot be used + --> $DIR/const_panic.rs:21:1 + | +LL | const X: () = unimplemented!(); + | ^^^^^^^^^^^^^^----------------^ + | | + | the evaluated program panicked at 'not yet implemented', $DIR/const_panic.rs:21:15 + | + = 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 3 previous errors + diff --git a/src/test/ui/const-eval/const_panic_libcore.rs b/src/test/ui/const-eval/const_panic_libcore.rs new file mode 100644 index 0000000000000..59aeca18129a8 --- /dev/null +++ b/src/test/ui/const-eval/const_panic_libcore.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![no_std] +#![crate_type = "lib"] +#![feature(const_panic)] + +const Z: () = panic!("cheese"); +//~^ ERROR this constant cannot be used + +const Y: () = unreachable!(); +//~^ ERROR this constant cannot be used + +const X: () = unimplemented!(); +//~^ ERROR this constant cannot be used diff --git a/src/test/ui/const-eval/const_panic_libcore.stderr b/src/test/ui/const-eval/const_panic_libcore.stderr new file mode 100644 index 0000000000000..45f2ee7744e82 --- /dev/null +++ b/src/test/ui/const-eval/const_panic_libcore.stderr @@ -0,0 +1,33 @@ +error: this constant cannot be used + --> $DIR/const_panic_libcore.rs:15:1 + | +LL | const Z: () = panic!("cheese"); + | ^^^^^^^^^^^^^^----------------^ + | | + | the evaluated program panicked at 'cheese', $DIR/const_panic_libcore.rs:15:15 + | + = note: #[deny(const_err)] on by default + = 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: this constant cannot be used + --> $DIR/const_panic_libcore.rs:18:1 + | +LL | const Y: () = unreachable!(); + | ^^^^^^^^^^^^^^--------------^ + | | + | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore.rs:18:15 + | + = 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: this constant cannot be used + --> $DIR/const_panic_libcore.rs:21:1 + | +LL | const X: () = unimplemented!(); + | ^^^^^^^^^^^^^^----------------^ + | | + | the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore.rs:21:15 + | + = 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 3 previous errors + diff --git a/src/test/ui/const-eval/const_panic_libcore_main.rs b/src/test/ui/const-eval/const_panic_libcore_main.rs new file mode 100644 index 0000000000000..bbbe827a8ef2c --- /dev/null +++ b/src/test/ui/const-eval/const_panic_libcore_main.rs @@ -0,0 +1,35 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "bin"] +#![feature(lang_items)] +#![feature(panic_implementation)] +#![feature(const_panic)] +#![no_main] +#![no_std] + +use core::panic::PanicInfo; + +const Z: () = panic!("cheese"); +//~^ ERROR this constant cannot be used + +const Y: () = unreachable!(); +//~^ ERROR this constant cannot be used + +const X: () = unimplemented!(); +//~^ ERROR this constant cannot be used + +#[lang = "eh_personality"] +fn eh() {} + +#[panic_implementation] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/test/ui/const-eval/const_panic_libcore_main.stderr b/src/test/ui/const-eval/const_panic_libcore_main.stderr new file mode 100644 index 0000000000000..7cb9f51c427a7 --- /dev/null +++ b/src/test/ui/const-eval/const_panic_libcore_main.stderr @@ -0,0 +1,33 @@ +error: this constant cannot be used + --> $DIR/const_panic_libcore_main.rs:20:1 + | +LL | const Z: () = panic!("cheese"); + | ^^^^^^^^^^^^^^----------------^ + | | + | the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:20:15 + | + = note: #[deny(const_err)] on by default + = 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: this constant cannot be used + --> $DIR/const_panic_libcore_main.rs:23:1 + | +LL | const Y: () = unreachable!(); + | ^^^^^^^^^^^^^^--------------^ + | | + | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:23:15 + | + = 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: this constant cannot be used + --> $DIR/const_panic_libcore_main.rs:26:1 + | +LL | const X: () = unimplemented!(); + | ^^^^^^^^^^^^^^----------------^ + | | + | the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore_main.rs:26:15 + | + = 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 3 previous errors + diff --git a/src/test/ui/const-eval/feature-gate-const_panic.rs b/src/test/ui/const-eval/feature-gate-const_panic.rs new file mode 100644 index 0000000000000..26eb95d9c662c --- /dev/null +++ b/src/test/ui/const-eval/feature-gate-const_panic.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} + +const Z: () = panic!("cheese"); +//~^ ERROR panicking in constants is unstable + +const Y: () = unreachable!(); +//~^ ERROR panicking in constants is unstable + +const X: () = unimplemented!(); +//~^ ERROR panicking in constants is unstable diff --git a/src/test/ui/const-eval/feature-gate-const_panic.stderr b/src/test/ui/const-eval/feature-gate-const_panic.stderr new file mode 100644 index 0000000000000..f4d05edd04a48 --- /dev/null +++ b/src/test/ui/const-eval/feature-gate-const_panic.stderr @@ -0,0 +1,30 @@ +error[E0658]: panicking in constants is unstable (see issue #51999) + --> $DIR/feature-gate-const_panic.rs:13:15 + | +LL | const Z: () = panic!("cheese"); + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_panic)] to the crate attributes to enable + = 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[E0658]: panicking in constants is unstable (see issue #51999) + --> $DIR/feature-gate-const_panic.rs:19:15 + | +LL | const X: () = unimplemented!(); + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_panic)] to the crate attributes to enable + = 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[E0658]: panicking in constants is unstable (see issue #51999) + --> $DIR/feature-gate-const_panic.rs:16:15 + | +LL | const Y: () = unreachable!(); + | ^^^^^^^^^^^^^^ + | + = help: add #![feature(const_panic)] to the crate attributes to enable + = 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 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-32829.rs b/src/test/ui/issues/issue-32829.rs index 60e83138c76e9..2d333f324c4d3 100644 --- a/src/test/ui/issues/issue-32829.rs +++ b/src/test/ui/issues/issue-32829.rs @@ -9,7 +9,7 @@ // except according to those terms. static S : u64 = { { panic!("foo"); 0 } }; -//~^ ERROR calls in statics are limited +//~^ ERROR panicking in statics is unstable fn main() { println!("{:?}", S); diff --git a/src/test/ui/issues/issue-32829.stderr b/src/test/ui/issues/issue-32829.stderr index 30b6a6429046c..55ee6d80d1f89 100644 --- a/src/test/ui/issues/issue-32829.stderr +++ b/src/test/ui/issues/issue-32829.stderr @@ -1,11 +1,12 @@ -error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants +error[E0658]: panicking in statics is unstable (see issue #51999) --> $DIR/issue-32829.rs:11:22 | LL | static S : u64 = { { panic!("foo"); 0 } }; | ^^^^^^^^^^^^^^ | + = help: add #![feature(const_panic)] to the crate attributes to enable = 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 -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0658`. From bd6ae6a6d10f3ebe51d0a7a8d7ef342a65f68ff4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 13 Aug 2018 14:27:29 +0200 Subject: [PATCH 2/2] Reexpose stability hole in the presence of feature gates --- src/libsyntax/feature_gate.rs | 2 +- src/test/ui/{ => consts}/const-eval/const_panic.rs | 0 src/test/ui/{ => consts}/const-eval/const_panic.stderr | 0 src/test/ui/{ => consts}/const-eval/const_panic_libcore.rs | 0 src/test/ui/{ => consts}/const-eval/const_panic_libcore.stderr | 0 src/test/ui/{ => consts}/const-eval/const_panic_libcore_main.rs | 2 ++ .../ui/{ => consts}/const-eval/const_panic_libcore_main.stderr | 0 src/test/ui/{ => consts}/const-eval/feature-gate-const_panic.rs | 0 .../ui/{ => consts}/const-eval/feature-gate-const_panic.stderr | 0 9 files changed, 3 insertions(+), 1 deletion(-) rename src/test/ui/{ => consts}/const-eval/const_panic.rs (100%) rename src/test/ui/{ => consts}/const-eval/const_panic.stderr (100%) rename src/test/ui/{ => consts}/const-eval/const_panic_libcore.rs (100%) rename src/test/ui/{ => consts}/const-eval/const_panic_libcore.stderr (100%) rename src/test/ui/{ => consts}/const-eval/const_panic_libcore_main.rs (94%) rename src/test/ui/{ => consts}/const-eval/const_panic_libcore_main.stderr (100%) rename src/test/ui/{ => consts}/const-eval/feature-gate-const_panic.rs (100%) rename src/test/ui/{ => consts}/const-eval/feature-gate-const_panic.stderr (100%) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4a819814d815c..6c33c4c245b9d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -225,7 +225,7 @@ declare_features! ( (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), // Allows panicking during const eval (produces compile-time errors) - (active, const_panic, "1.29.0", Some(51999), None), + (active, const_panic, "1.30.0", Some(51999), None), // Allows using #[prelude_import] on glob `use` items. // diff --git a/src/test/ui/const-eval/const_panic.rs b/src/test/ui/consts/const-eval/const_panic.rs similarity index 100% rename from src/test/ui/const-eval/const_panic.rs rename to src/test/ui/consts/const-eval/const_panic.rs diff --git a/src/test/ui/const-eval/const_panic.stderr b/src/test/ui/consts/const-eval/const_panic.stderr similarity index 100% rename from src/test/ui/const-eval/const_panic.stderr rename to src/test/ui/consts/const-eval/const_panic.stderr diff --git a/src/test/ui/const-eval/const_panic_libcore.rs b/src/test/ui/consts/const-eval/const_panic_libcore.rs similarity index 100% rename from src/test/ui/const-eval/const_panic_libcore.rs rename to src/test/ui/consts/const-eval/const_panic_libcore.rs diff --git a/src/test/ui/const-eval/const_panic_libcore.stderr b/src/test/ui/consts/const-eval/const_panic_libcore.stderr similarity index 100% rename from src/test/ui/const-eval/const_panic_libcore.stderr rename to src/test/ui/consts/const-eval/const_panic_libcore.stderr diff --git a/src/test/ui/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs similarity index 94% rename from src/test/ui/const-eval/const_panic_libcore_main.rs rename to src/test/ui/consts/const-eval/const_panic_libcore_main.rs index bbbe827a8ef2c..c66e1fe4bf5a9 100644 --- a/src/test/ui/const-eval/const_panic_libcore_main.rs +++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs @@ -28,6 +28,8 @@ const X: () = unimplemented!(); #[lang = "eh_personality"] fn eh() {} +#[lang = "eh_unwind_resume"] +fn eh_unwind_resume() {} #[panic_implementation] fn panic(_info: &PanicInfo) -> ! { diff --git a/src/test/ui/const-eval/const_panic_libcore_main.stderr b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr similarity index 100% rename from src/test/ui/const-eval/const_panic_libcore_main.stderr rename to src/test/ui/consts/const-eval/const_panic_libcore_main.stderr diff --git a/src/test/ui/const-eval/feature-gate-const_panic.rs b/src/test/ui/consts/const-eval/feature-gate-const_panic.rs similarity index 100% rename from src/test/ui/const-eval/feature-gate-const_panic.rs rename to src/test/ui/consts/const-eval/feature-gate-const_panic.rs diff --git a/src/test/ui/const-eval/feature-gate-const_panic.stderr b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr similarity index 100% rename from src/test/ui/const-eval/feature-gate-const_panic.stderr rename to src/test/ui/consts/const-eval/feature-gate-const_panic.stderr