提交 bb78426c 编写于 作者: O Oliver Schneider

Allow panicking with string literal messages inside constants

上级 674ef668
...@@ -536,7 +536,6 @@ fn hash_stable<W: StableHasherResult>(&self, ...@@ -536,7 +536,6 @@ fn hash_stable<W: StableHasherResult>(&self,
DeallocateNonBasePtr | DeallocateNonBasePtr |
HeapAllocZeroBytes | HeapAllocZeroBytes |
Unreachable | Unreachable |
Panic |
ReadFromReturnPointer | ReadFromReturnPointer |
UnimplementedTraitSelection | UnimplementedTraitSelection |
TypeckError | TypeckError |
...@@ -550,6 +549,12 @@ fn hash_stable<W: StableHasherResult>(&self, ...@@ -550,6 +549,12 @@ fn hash_stable<W: StableHasherResult>(&self,
GeneratorResumedAfterReturn | GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic | GeneratorResumedAfterPanic |
InfiniteLoop => {} 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), ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
MachineError(ref err) => err.hash_stable(hcx, hasher), MachineError(ref err) => err.hash_stable(hcx, hasher),
FunctionPointerTyMismatch(a, b) => { FunctionPointerTyMismatch(a, b) => {
......
...@@ -305,6 +305,8 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems { ...@@ -305,6 +305,8 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn; PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn;
PanicInfoLangItem, "panic_info", panic_info; PanicInfoLangItem, "panic_info", panic_info;
PanicImplLangItem, "panic_impl", panic_impl; 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; ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
BoxFreeFnLangItem, "box_free", box_free_fn; BoxFreeFnLangItem, "box_free", box_free_fn;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
use syntax_pos::Span; use syntax_pos::Span;
use syntax::ast; use syntax::ast;
use syntax::symbol::Symbol;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>; pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc<ConstEvalErr<'tcx>>>;
...@@ -250,7 +251,12 @@ pub enum EvalErrorKind<'tcx, O> { ...@@ -250,7 +251,12 @@ pub enum EvalErrorKind<'tcx, O> {
HeapAllocZeroBytes, HeapAllocZeroBytes,
HeapAllocNonPowerOfTwoAlignment(u64), HeapAllocNonPowerOfTwoAlignment(u64),
Unreachable, Unreachable,
Panic, Panic {
msg: Symbol,
line: u32,
col: u32,
file: Symbol,
},
ReadFromReturnPointer, ReadFromReturnPointer,
PathNotFound(Vec<String>), PathNotFound(Vec<String>),
UnimplementedTraitSelection, UnimplementedTraitSelection,
...@@ -370,7 +376,7 @@ pub fn description(&self) -> &str { ...@@ -370,7 +376,7 @@ pub fn description(&self) -> &str {
"tried to re-, de-, or allocate heap memory with alignment that is not a power of two", "tried to re-, de-, or allocate heap memory with alignment that is not a power of two",
Unreachable => Unreachable =>
"entered unreachable code", "entered unreachable code",
Panic => Panic { .. } =>
"the evaluated program panicked", "the evaluated program panicked",
ReadFromReturnPointer => ReadFromReturnPointer =>
"tried to read from the return pointer", "tried to read from the return pointer",
...@@ -465,6 +471,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ...@@ -465,6 +471,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", inner), write!(f, "{}", inner),
IncorrectAllocationInformation(size, size2, align, align2) => 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()), 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()), _ => write!(f, "{}", self.description()),
} }
} }
......
...@@ -574,7 +574,11 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif ...@@ -574,7 +574,11 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
HeapAllocZeroBytes => HeapAllocZeroBytes, HeapAllocZeroBytes => HeapAllocZeroBytes,
HeapAllocNonPowerOfTwoAlignment(n) => HeapAllocNonPowerOfTwoAlignment(n), HeapAllocNonPowerOfTwoAlignment(n) => HeapAllocNonPowerOfTwoAlignment(n),
Unreachable => Unreachable, Unreachable => Unreachable,
Panic => Panic, Panic { ref msg, ref file, line, col } => Panic {
msg: msg.clone(),
file: file.clone(),
line, col,
},
ReadFromReturnPointer => ReadFromReturnPointer, ReadFromReturnPointer => ReadFromReturnPointer,
PathNotFound(ref v) => PathNotFound(v.clone()), PathNotFound(ref v) => PathNotFound(v.clone()),
UnimplementedTraitSelection => UnimplementedTraitSelection, UnimplementedTraitSelection => UnimplementedTraitSelection,
......
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
use rustc::mir::interpret::ConstEvalErr; use rustc::mir::interpret::ConstEvalErr;
use rustc::mir; use rustc::mir;
use rustc::ty::{self, TyCtxt, Instance}; 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::ty::subst::Subst;
use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use syntax::ast::Mutability; use syntax::ast::Mutability;
use syntax::source_map::Span; use syntax::source_map::Span;
use syntax::source_map::DUMMY_SP; use syntax::source_map::DUMMY_SP;
use syntax::symbol::Symbol;
use rustc::mir::interpret::{ use rustc::mir::interpret::{
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalResult, EvalError, EvalErrorKind, GlobalId,
...@@ -19,7 +20,7 @@ ...@@ -19,7 +20,7 @@
}; };
use super::{ use super::{
Place, PlaceExtra, PlaceTy, MemPlace, OpTy, Operand, Value, 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>( pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
...@@ -237,13 +238,7 @@ fn eval_fn_call<'a>( ...@@ -237,13 +238,7 @@ fn eval_fn_call<'a>(
if !ecx.tcx.is_const_fn(instance.def_id()) { if !ecx.tcx.is_const_fn(instance.def_id()) {
let def_id = instance.def_id(); let def_id = instance.def_id();
// Some fn calls are actually BinOp intrinsics // Some fn calls are actually BinOp intrinsics
let (op, oflo) = if let Some(op) = ecx.tcx.is_binop_lang_item(def_id) { let _: ! = if let Some((op, oflo)) = ecx.tcx.is_binop_lang_item(def_id) {
op
} else {
return Err(
ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into(),
);
};
let (dest, bb) = destination.expect("128 lowerings can't diverge"); let (dest, bb) = destination.expect("128 lowerings can't diverge");
let l = ecx.read_value(args[0])?; let l = ecx.read_value(args[0])?;
let r = ecx.read_value(args[1])?; let r = ecx.read_value(args[1])?;
...@@ -254,6 +249,45 @@ fn eval_fn_call<'a>( ...@@ -254,6 +249,45 @@ fn eval_fn_call<'a>(
} }
ecx.goto_block(bb); ecx.goto_block(bb);
return Ok(true); 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 mir = match ecx.load_mir(instance.def) { let mir = match ecx.load_mir(instance.def) {
Ok(mir) => mir, Ok(mir) => mir,
...@@ -412,6 +446,39 @@ fn global_item_with_linkage<'a>( ...@@ -412,6 +446,39 @@ fn global_item_with_linkage<'a>(
} }
} }
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 /// Project to a field of a (variant of a) const
pub fn const_field<'a, 'tcx>( pub fn const_field<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
......
...@@ -213,7 +213,7 @@ fn from_known_layout<'tcx>( ...@@ -213,7 +213,7 @@ fn from_known_layout<'tcx>(
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { 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. /// 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. /// 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, &self,
mplace: MPlaceTy<'tcx>, mplace: MPlaceTy<'tcx>,
) -> EvalResult<'tcx, Option<Value>> { ) -> EvalResult<'tcx, Option<Value>> {
......
...@@ -230,7 +230,7 @@ fn use_ecx<F, T>( ...@@ -230,7 +230,7 @@ fn use_ecx<F, T>(
// FIXME: implement // FIXME: implement
=> {}, => {},
| Panic | Panic { .. }
| BoundsCheck{..} | BoundsCheck{..}
| Overflow(_) | Overflow(_)
| OverflowNeg | OverflowNeg
......
...@@ -400,6 +400,11 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) { ...@@ -400,6 +400,11 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
(self.qualif, Lrc::new(promoted_temps)) (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. /// Accumulates an Rvalue or Call's effects in self.qualif.
...@@ -834,7 +839,7 @@ fn visit_terminator_kind(&mut self, ...@@ -834,7 +839,7 @@ fn visit_terminator_kind(&mut self,
} }
} }
_ => { _ => {
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); is_const_fn = Some(def_id);
} }
} }
...@@ -880,8 +885,25 @@ fn visit_terminator_kind(&mut self, ...@@ -880,8 +885,25 @@ fn visit_terminator_kind(&mut self,
// Const fn calls. // Const fn calls.
if let Some(def_id) = is_const_fn { if let Some(def_id) = is_const_fn {
// check the const_panic feature gate or
// find corresponding rustc_const_unstable feature // 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 { rustc_const_unstable: Some(attr::RustcConstUnstable {
feature: ref feature_name feature: ref feature_name
}), }),
......
...@@ -397,6 +397,7 @@ fn get(&mut self) -> &(dyn Any + Send) { ...@@ -397,6 +397,7 @@ fn get(&mut self) -> &(dyn Any + Send) {
#[unstable(feature = "libstd_sys_internals", #[unstable(feature = "libstd_sys_internals",
reason = "used by the panic! macro", reason = "used by the panic! macro",
issue = "0")] 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 #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! { pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! {
// Note that this should be the only allocation performed in this code path. // Note that this should be the only allocation performed in this code path.
......
...@@ -224,6 +224,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F) ...@@ -224,6 +224,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
// Allows comparing raw pointers during const eval // Allows comparing raw pointers during const eval
(active, const_compare_raw_pointers, "1.27.0", Some(53020), None), (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. // Allows using #[prelude_import] on glob `use` items.
// //
// rustc internal // rustc internal
......
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
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
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
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
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 {}
}
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
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
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`.
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
// except according to those terms. // except according to those terms.
static S : u64 = { { panic!("foo"); 0 } }; static S : u64 = { { panic!("foo"); 0 } };
//~^ ERROR calls in statics are limited //~^ ERROR panicking in statics is unstable
fn main() { fn main() {
println!("{:?}", S); println!("{:?}", S);
......
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 --> $DIR/issue-32829.rs:11:22
| |
LL | static S : u64 = { { panic!("foo"); 0 } }; 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) = 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 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`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册