From 1ede46bb339ca8a760ca302e3fa8697be328cc4f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 28 Jun 2021 22:32:56 +0200 Subject: [PATCH 1/5] Make `const_panic` work with the 2021 edition --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 4 +++ compiler/rustc_hir/src/lang_items.rs | 1 + .../rustc_mir/src/const_eval/fn_queries.rs | 9 +++-- compiler/rustc_mir/src/const_eval/machine.rs | 29 ++++++++++++++++ .../interpret/intrinsics/caller_location.rs | 5 +++ compiler/rustc_mir/src/interpret/place.rs | 8 +++-- compiler/rustc_span/src/symbol.rs | 3 ++ compiler/rustc_typeck/src/check/intrinsic.rs | 13 ++++++++ library/core/src/fmt/mod.rs | 4 +-- library/core/src/intrinsics.rs | 6 ++++ library/core/src/lib.rs | 4 +++ library/core/src/option.rs | 1 + library/core/src/panic.rs | 14 ++++---- library/core/src/panicking.rs | 33 +++++++++++++++++++ 14 files changed, 120 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1fb201eda6bb0..fb5d14f4d1f14 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -107,6 +107,10 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { &args.iter().map(|arg| arg.immediate()).collect::>(), None, ), + sym::panic_ctfe_hook => { + // Does nothing at runtime. + return; + } sym::likely => { let expect = self.get_intrinsic(&("llvm.expect.i1")); self.call(expect, &[args[0].immediate(), self.const_bool(true)], None) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index bab685006eafc..71c5dbe081ddb 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -327,6 +327,7 @@ language_item_table! { FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }); + Option, sym::Option, option_ty, Target::Enum; OptionSome, sym::Some, option_some_variant, Target::Variant; OptionNone, sym::None, option_none_variant, Target::Variant; diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs index 40419a4d201ac..a9126172e232e 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs @@ -48,9 +48,12 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool { if let hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) = node { - // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other - // foreign items cannot be evaluated at compile-time. - if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = tcx.hir().get_foreign_abi(hir_id) { + // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. + // `panic_impl` also does in order to pass const checks (it is never evaluated at compile + // time). + if let Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic = + tcx.hir().get_foreign_abi(hir_id) + { tcx.lookup_const_stability(def_id).is_some() } else { false diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs index 773df7d7b60c1..f4ae09a933a34 100644 --- a/compiler/rustc_mir/src/const_eval/machine.rs +++ b/compiler/rustc_mir/src/const_eval/machine.rs @@ -309,6 +309,35 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ); ecx.write_scalar(Scalar::Ptr(ptr), dest)?; } + sym::panic_ctfe_hook => { + // Option<&str> + assert!(args.len() == 1); + + debug!("panic_ctfe_hook: invoked with {:?}", args[0]); + + let (_, idx) = ecx.read_discriminant(&args[0])?; + let some = match idx.index() { + 0 => { + // None + // For now, this is unreachable code - you cannot construct a non-literal + // `fmt::Arguments` without `impl const Display`, which we don't currently + // provide. + unreachable!("non-literal `fmt::Arguments` used in const panic"); + } + 1 => { + // Some + ecx.operand_downcast(&args[0], idx)? + } + _ => unreachable!("encountered `Option` with variant {:?}", idx), + }; + + let ref_msg = ecx.operand_field(&some, 0)?; + let msg_place = ecx.deref_operand(&ref_msg)?; + let msg = Symbol::intern(ecx.read_str(&msg_place)?); + let span = ecx.find_closest_untracked_caller_location(); + let (file, line, col) = ecx.location_triple_for_span(span); + return Err(ConstEvalErrKind::Panic { msg, file, line, col }.into()); + } _ => { return Err(ConstEvalErrKind::NeedsRfc(format!( "calling intrinsic `{}`", diff --git a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs index 792a4749108be..c15f37d0231ff 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs @@ -51,6 +51,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Stop inside the most nested non-`#[track_caller]` function, // before ever reaching its caller (which is irrelevant). if !callee.def.requires_caller_location(*self.tcx) { + debug!( + "find_closest_untracked_caller_location: result (inlined) is {:?}", + source_info.span + ); return source_info.span; } source_info.span = callsite_span; @@ -66,6 +70,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Stop inside the most nested non-`#[track_caller]` function, // before ever reaching its caller (which is irrelevant). if !frame.instance.def.requires_caller_location(*self.tcx) { + debug!("find_closest_untracked_caller_location: result is {:?}", source_info.span); return source_info.span; } } diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs index 4c53510ed00ee..7453900938a6e 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_mir/src/interpret/place.rs @@ -303,8 +303,12 @@ where &self, val: &ImmTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { - let pointee_type = - val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty; + let pointee_type = val + .layout + .ty + .builtin_deref(true) + .unwrap_or_else(|| panic!("`ref_to_mplace` called on non-ptr type {}", val.layout.ty)) + .ty; let layout = self.layout_of(pointee_type)?; let (ptr, meta) = match **val { Immediate::Scalar(ptr) => (ptr.check_init()?, MemPlaceMeta::None), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index be4f12c6d1cb8..19adf454a3e5d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -275,6 +275,7 @@ symbols! { any, arbitrary_enum_discriminant, arbitrary_self_types, + arguments_as_str, arith_offset, arm, arm_target_feature, @@ -853,6 +854,8 @@ symbols! { panic_2021, panic_abort, panic_bounds_check, + panic_ctfe_hook, + panic_fmt, panic_handler, panic_impl, panic_implementation, diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 882d5d54b7c9f..ce65ce8da330e 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -7,6 +7,7 @@ use crate::errors::{ }; use crate::require_same_types; +use hir::LangItem; use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; @@ -297,6 +298,18 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8)) } + sym::panic_ctfe_hook => { + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; + let ref_str = tcx + .mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), tcx.types.str_); + let option_def_id = tcx.require_lang_item(LangItem::Option, None); + let adt_def = tcx.adt_def(option_def_id); + let substs = tcx.mk_substs([ref_str.into()].iter()); + let opt = tcx.mk_adt(&adt_def, substs); + + (0, vec![opt], tcx.types.unit) + } + sym::ptr_offset_from => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 9ed49c1e3024f..ca4f3516c43ee 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -334,7 +334,7 @@ impl<'a> Arguments<'a> { #[doc(hidden)] #[inline] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - pub fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { + pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { Arguments { pieces, fmt: None, args } } @@ -347,7 +347,7 @@ impl<'a> Arguments<'a> { #[doc(hidden)] #[inline] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] - pub fn new_v1_formatted( + pub const fn new_v1_formatted( pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>], fmt: &'a [rt::v1::Argument], diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index b4311bbe5f41f..87313fcaebd69 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -719,6 +719,7 @@ extern "rust-intrinsic" { /// /// A more user-friendly and stable version of this operation is /// [`std::process::abort`](../../std/process/fn.abort.html). + #[rustc_const_unstable(feature = "const_abort", issue = "none")] pub fn abort() -> !; /// Informs the optimizer that this point in the code is not reachable, @@ -1907,6 +1908,11 @@ extern "rust-intrinsic" { /// Allocate at compile time. Should not be called at runtime. #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub fn const_allocate(size: usize, align: usize) -> *mut u8; + + /// Implementation detail of the `const_panic` feature. + #[rustc_const_unstable(feature = "panic_ctfe_hook", issue = "none")] + #[cfg(not(bootstrap))] + pub fn panic_ctfe_hook(message: Option<&str>); } // Some functions are defined here because they accidentally got made diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7fa8202e5d60a..b95926ec2a87c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -67,6 +67,8 @@ #![feature(asm)] #![feature(bool_to_option)] #![feature(cfg_target_has_atomic)] +#![feature(const_abort)] +#![feature(const_arguments_as_str)] #![feature(const_heap)] #![feature(const_alloc_layout)] #![feature(const_assert_type)] @@ -81,6 +83,7 @@ #![feature(const_mut_refs)] #![feature(const_refs_to_cell)] #![feature(const_panic)] +#![cfg_attr(not(bootstrap), feature(const_panic_impl))] #![feature(const_pin)] #![feature(const_fn_union)] #![feature(const_impl_trait)] @@ -124,6 +127,7 @@ #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(auto_traits)] +#![cfg_attr(not(bootstrap), feature(panic_ctfe_hook))] #![feature(prelude_import)] #![feature(ptr_metadata)] #![feature(repr_simd, platform_intrinsics)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 13de1cb309211..b74992ce5c89d 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -160,6 +160,7 @@ use crate::{ #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[rustc_diagnostic_item = "option_type"] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), lang = "Option")] pub enum Option { /// No value #[lang = "None"] diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index cbb10c324c495..0d88365a8a5b7 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -65,7 +65,7 @@ pub macro panic_2021 { #[stable(feature = "panic_hooks", since = "1.10.0")] #[derive(Debug)] pub struct PanicInfo<'a> { - payload: &'a (dyn Any + Send), + payload: Option<&'a (dyn Any + Send)>, message: Option<&'a fmt::Arguments<'a>>, location: &'a Location<'a>, } @@ -78,12 +78,11 @@ impl<'a> PanicInfo<'a> { )] #[doc(hidden)] #[inline] - pub fn internal_constructor( + pub const fn internal_constructor( message: Option<&'a fmt::Arguments<'a>>, location: &'a Location<'a>, ) -> Self { - struct NoPayload; - PanicInfo { location, message, payload: &NoPayload } + PanicInfo { location, message, payload: None } } #[unstable( @@ -94,7 +93,7 @@ impl<'a> PanicInfo<'a> { #[doc(hidden)] #[inline] pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) { - self.payload = info; + self.payload = Some(info); } /// Returns the payload associated with the panic. @@ -120,7 +119,8 @@ impl<'a> PanicInfo<'a> { /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn payload(&self) -> &(dyn Any + Send) { - self.payload + struct NoPayload; + self.payload.unwrap_or(&NoPayload) } /// If the `panic!` macro from the `core` crate (not from `std`) @@ -169,7 +169,7 @@ impl fmt::Display for PanicInfo<'_> { formatter.write_str("panicked at ")?; if let Some(message) = self.message { write!(formatter, "'{}', ", message)? - } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() { + } else if let Some(payload) = self.payload().downcast_ref::<&'static str>() { write!(formatter, "'{}', ", payload)? } // NOTE: we cannot use downcast_ref::() here diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 3e3e96fcd7f78..841e1d73b3b17 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -74,6 +74,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] +#[cfg(bootstrap)] pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() @@ -92,6 +93,38 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { unsafe { panic_impl(&pi) } } +/// The underlying implementation of libcore's `panic!` macro when formatting is used. +#[cold] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[track_caller] +#[cfg(not(bootstrap))] +pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + #[rustc_const_unstable(feature = "const_panic_impl", issue = "none")] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + #[cfg(not(bootstrap))] + unsafe { + // If we're const-evaluating this panic, this call will abort evaluation and unwind. + // The code below is only reachable during runtime. + core::intrinsics::panic_ctfe_hook(fmt.as_str()); + } + + let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller()); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } +} + #[derive(Debug)] #[doc(hidden)] pub enum AssertKind { From 948369e79fac2a9613035c056edd38824c9cc4eb Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 3 Jul 2021 00:06:23 +0200 Subject: [PATCH 2/5] Add safety comment --- library/core/src/panicking.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 841e1d73b3b17..30f2875703178 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -113,6 +113,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { } #[cfg(not(bootstrap))] + // SAFETY: the intrinsic is always safe to call. unsafe { // If we're const-evaluating this panic, this call will abort evaluation and unwind. // The code below is only reachable during runtime. From 835325937fca07ac69e1093a5d0309f0bc111d7e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 3 Jul 2021 00:06:31 +0200 Subject: [PATCH 3/5] Bless test --- src/test/ui/borrowck/issue-64453.rs | 1 - src/test/ui/borrowck/issue-64453.stderr | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/test/ui/borrowck/issue-64453.rs b/src/test/ui/borrowck/issue-64453.rs index 3e803f3b6d8b2..3cfeb86cdc32a 100644 --- a/src/test/ui/borrowck/issue-64453.rs +++ b/src/test/ui/borrowck/issue-64453.rs @@ -3,7 +3,6 @@ struct Value; static settings_dir: String = format!(""); //~^ ERROR calls in statics are limited to constant functions -//~| ERROR calls in statics are limited to constant functions fn from_string(_: String) -> Value { Value diff --git a/src/test/ui/borrowck/issue-64453.stderr b/src/test/ui/borrowck/issue-64453.stderr index bd8270ef958cb..29b05068ac74d 100644 --- a/src/test/ui/borrowck/issue-64453.stderr +++ b/src/test/ui/borrowck/issue-64453.stderr @@ -1,17 +1,9 @@ error[E0507]: cannot move out of static item `settings_dir` - --> $DIR/issue-64453.rs:14:37 + --> $DIR/issue-64453.rs:13:37 | LL | let settings_data = from_string(settings_dir); | ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait -error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants - --> $DIR/issue-64453.rs:4:31 - | -LL | static settings_dir: String = format!(""); - | ^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants --> $DIR/issue-64453.rs:4:31 | @@ -20,7 +12,7 @@ LL | static settings_dir: String = format!(""); | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0015, E0507. For more information about an error, try `rustc --explain E0015`. From 80301a3d27ef5c56e8672ac4d384ad975666e67e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 3 Jul 2021 00:29:46 +0200 Subject: [PATCH 4/5] Add test for const panic in 2021 edition --- .../ui/consts/const-eval/const_panic_2021.rs | 31 ++++++++ .../consts/const-eval/const_panic_2021.stderr | 79 +++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/test/ui/consts/const-eval/const_panic_2021.rs create mode 100644 src/test/ui/consts/const-eval/const_panic_2021.stderr diff --git a/src/test/ui/consts/const-eval/const_panic_2021.rs b/src/test/ui/consts/const-eval/const_panic_2021.rs new file mode 100644 index 0000000000000..dbf9aca6166c8 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_panic_2021.rs @@ -0,0 +1,31 @@ +// edition:2021 + +// NB: panic macros without arguments share the 2015/2018 edition hook +// We cannot annotate the expected error in the test because it point at libcore +// FIXME: this is a very bad error message + +#![feature(const_panic)] +#![allow(non_fmt_panic)] +#![crate_type = "lib"] + +const Z: () = std::panic!("cheese"); + +const Z2: () = std::panic!(); +//~^ ERROR evaluation of constant value failed + +const Y: () = std::unreachable!(); +//~^ ERROR evaluation of constant value failed + +const X: () = std::unimplemented!(); +//~^ ERROR evaluation of constant value failed + +const Z_CORE: () = core::panic!("cheese"); + +const Z2_CORE: () = core::panic!(); +//~^ ERROR evaluation of constant value failed + +const Y_CORE: () = core::unreachable!(); +//~^ ERROR evaluation of constant value failed + +const X_CORE: () = core::unimplemented!(); +//~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-eval/const_panic_2021.stderr b/src/test/ui/consts/const-eval/const_panic_2021.stderr new file mode 100644 index 0000000000000..1a18efc269d46 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_panic_2021.stderr @@ -0,0 +1,79 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/panicking.rs:LL:COL + | +LL | core::intrinsics::panic_ctfe_hook(fmt.as_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the evaluated program panicked at 'cheese', $DIR/const_panic_2021.rs:11:15 + | inside `panic_fmt` at $SRC_DIR/core/src/panicking.rs:LL:COL + | + ::: $DIR/const_panic_2021.rs:11:15 + | +LL | const Z: () = std::panic!("cheese"); + | --------------------- inside `Z` at $SRC_DIR/core/src/panic.rs:LL:COL + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:13:16 + | +LL | const Z2: () = std::panic!(); + | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:13:16 + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:16:15 + | +LL | const Y: () = std::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:16:15 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:19:15 + | +LL | const X: () = std::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:19:15 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/panicking.rs:LL:COL + | +LL | core::intrinsics::panic_ctfe_hook(fmt.as_str()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the evaluated program panicked at 'cheese', $DIR/const_panic_2021.rs:22:20 + | inside `panic_fmt` at $SRC_DIR/core/src/panicking.rs:LL:COL + | + ::: $DIR/const_panic_2021.rs:22:20 + | +LL | const Z_CORE: () = core::panic!("cheese"); + | ---------------------- inside `Z_CORE` at $SRC_DIR/core/src/panic.rs:LL:COL + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:24:21 + | +LL | const Z2_CORE: () = core::panic!(); + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:24:21 + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:27:20 + | +LL | const Y_CORE: () = core::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:27:20 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:30:20 + | +LL | const X_CORE: () = core::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:30:20 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0080`. From c360d6f4727bc182c223230c8fa08f7ac350bef3 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 3 Jul 2021 19:07:15 +0200 Subject: [PATCH 5/5] Address review comments --- library/core/src/intrinsics.rs | 5 +++++ library/core/src/panicking.rs | 17 +++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 87313fcaebd69..106961c01853e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1910,6 +1910,11 @@ extern "rust-intrinsic" { pub fn const_allocate(size: usize, align: usize) -> *mut u8; /// Implementation detail of the `const_panic` feature. + /// + /// The panic code calls this with the result of `fmt::Arguments::as_str`. + /// Since it is currently impossible to construct a non-literal + /// `fmt::Arguments` in a const context, this will always be a `Some` + /// containing the panic message. #[rustc_const_unstable(feature = "panic_ctfe_hook", issue = "none")] #[cfg(not(bootstrap))] pub fn panic_ctfe_hook(message: Option<&str>); diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 30f2875703178..d0186a3776d24 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -100,26 +100,27 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { #[track_caller] #[cfg(not(bootstrap))] pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { + // SAFETY: the intrinsic is always safe to call. + unsafe { + // If we're const-evaluating this panic, this call will abort evaluation and unwind. + // The code below is only reachable during runtime. + core::intrinsics::panic_ctfe_hook(fmt.as_str()); + } + if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call // that gets resolved to the `#[panic_handler]` function. + // While it is marked `rustc_const_unstable`, it will never actually be called during CTFE + // (the `panic_ctfe_hook` will stop execution). extern "Rust" { #[lang = "panic_impl"] #[rustc_const_unstable(feature = "const_panic_impl", issue = "none")] fn panic_impl(pi: &PanicInfo<'_>) -> !; } - #[cfg(not(bootstrap))] - // SAFETY: the intrinsic is always safe to call. - unsafe { - // If we're const-evaluating this panic, this call will abort evaluation and unwind. - // The code below is only reachable during runtime. - core::intrinsics::panic_ctfe_hook(fmt.as_str()); - } - let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller()); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.