Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow panic!("{}", computed_str) in const fn. #88954

Merged
merged 1 commit into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 7 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,17 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
let def_id = instance.def_id();
if Some(def_id) == self.tcx.lang_items().panic_fn()
|| Some(def_id) == self.tcx.lang_items().panic_str()
|| Some(def_id) == self.tcx.lang_items().panic_display()
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
{
// &str
// &str or &&str
assert!(args.len() == 1);

let msg_place = self.deref_operand(&args[0])?;
let mut msg_place = self.deref_operand(&args[0])?;
while msg_place.layout.ty.is_ref() {
msg_place = self.deref_operand(&msg_place.into())?;
}

let msg = Symbol::intern(self.read_str(&msg_place)?);
let span = self.find_closest_untracked_caller_location();
let (file, line, col) = self.location_triple_for_span(span);
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
if is_lang_panic_fn(tcx, callee) {
self.check_op(ops::Panic);

// `begin_panic` and `panic_display` are generic functions that accept
// types other than str. Check to enforce that only str can be used in
// const-eval.

// const-eval of the `begin_panic` fn assumes the argument is `&str`
if Some(callee) == tcx.lang_items().begin_panic_fn() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
Expand All @@ -896,6 +900,15 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
}
}

// const-eval of the `panic_display` fn assumes the argument is `&&str`
nbdd0121 marked this conversation as resolved.
Show resolved Hide resolved
if Some(callee) == tcx.lang_items().panic_display() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
{}
_ => self.check_op(ops::PanicNonStr),
}
}

return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
// Keep in sync with what that function handles!
Some(def_id) == tcx.lang_items().panic_fn()
|| Some(def_id) == tcx.lang_items().panic_str()
|| Some(def_id) == tcx.lang_items().panic_display()
|| Some(def_id) == tcx.lang_items().begin_panic_fn()
|| Some(def_id) == tcx.lang_items().panic_fmt()
|| Some(def_id) == tcx.lang_items().begin_panic_fmt()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ language_item_table! {
// a weak lang item, but do not have it defined.
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ symbols! {
panic_2021,
panic_abort,
panic_bounds_check,
panic_display,
panic_fmt,
panic_handler,
panic_impl,
Expand Down
9 changes: 9 additions & 0 deletions library/core/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ pub macro panic_2015 {
($msg:literal $(,)?) => (
$crate::panicking::panic($msg)
),
// Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
($msg:expr $(,)?) => (
$crate::panicking::panic_str($msg)
),
// Special-case the single-argument case for const_panic.
("{}", $arg:expr $(,)?) => (
$crate::panicking::panic_display(&$arg)
),
($fmt:expr, $($arg:tt)+) => (
$crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
),
Expand All @@ -44,6 +49,10 @@ pub macro panic_2021 {
() => (
$crate::panicking::panic("explicit panic")
),
// Special-case the single-argument case for const_panic.
("{}", $arg:expr $(,)?) => (
$crate::panicking::panic_display(&$arg)
),
($($t:tt)+) => (
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
),
Expand Down
7 changes: 7 additions & 0 deletions library/core/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ pub fn panic_str(expr: &str) -> ! {
panic_fmt(format_args!("{}", expr));
}

#[inline]
#[track_caller]
#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics
pub fn panic_display<T: fmt::Display>(x: &T) -> ! {
m-ou-se marked this conversation as resolved.
Show resolved Hide resolved
panic_fmt(format_args!("{}", *x));
}

#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
Expand Down
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
#![feature(const_trait_impl)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]
#![feature(core_panic)]
#![feature(custom_test_frameworks)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
Expand Down
6 changes: 5 additions & 1 deletion library/std/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::thread::Result;

#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
#[allow_internal_unstable(libstd_sys_internals, const_format_args)]
#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
#[rustc_macro_transparency = "semitransparent"]
pub macro panic_2015 {
Expand All @@ -20,6 +20,10 @@ pub macro panic_2015 {
($msg:expr $(,)?) => ({
$crate::rt::begin_panic($msg)
}),
// Special-case the single-argument case for const_panic.
("{}", $arg:expr $(,)?) => ({
$crate::rt::panic_display(&$arg)
}),
($fmt:expr, $($arg:tt)+) => ({
$crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+))
}),
Expand Down
1 change: 1 addition & 0 deletions library/std/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

// Re-export some of our utilities which are expected by other crates.
pub use crate::panicking::{begin_panic, begin_panic_fmt, panic_count};
pub use core::panicking::panic_display;

// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
Expand Down
8 changes: 7 additions & 1 deletion src/test/ui/consts/const-eval/const_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ const Y: () = std::unreachable!();

const X: () = std::unimplemented!();
//~^ ERROR evaluation of constant value failed
//

const W: () = std::panic!(MSG);
//~^ ERROR evaluation of constant value failed

const W2: () = std::panic!("{}", MSG);
//~^ ERROR evaluation of constant value failed

const Z_CORE: () = core::panic!("cheese");
//~^ ERROR evaluation of constant value failed

Expand All @@ -33,3 +36,6 @@ const X_CORE: () = core::unimplemented!();

const W_CORE: () = core::panic!(MSG);
//~^ ERROR evaluation of constant value failed

const W2_CORE: () = core::panic!("{}", MSG);
//~^ ERROR evaluation of constant value failed
38 changes: 27 additions & 11 deletions src/test/ui/consts/const-eval/const_panic.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -39,45 +39,61 @@ LL | const W: () = std::panic!(MSG);
= 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.rs:22:20
--> $DIR/const_panic.rs:22:16
|
LL | const W2: () = std::panic!("{}", MSG);
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:22:16
|
= 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.rs:25:20
|
LL | const Z_CORE: () = core::panic!("cheese");
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:25: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.rs:25:21
--> $DIR/const_panic.rs:28:21
|
LL | const Z2_CORE: () = core::panic!();
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:28:21
|
= 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.rs:28:20
--> $DIR/const_panic.rs:31:20
|
LL | const Y_CORE: () = core::unreachable!();
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:31: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.rs:31:20
--> $DIR/const_panic.rs:34:20
|
LL | const X_CORE: () = core::unimplemented!();
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:34: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.rs:34:20
--> $DIR/const_panic.rs:37:20
|
LL | const W_CORE: () = core::panic!(MSG);
| ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20
| ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:37: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.rs:40:21
|
LL | const W2_CORE: () = core::panic!("{}", MSG);
| ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:40:21
|
= 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 10 previous errors
error: aborting due to 12 previous errors

For more information about this error, try `rustc --explain E0080`.
16 changes: 12 additions & 4 deletions src/test/ui/consts/const-eval/const_panic_2021.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#![feature(const_panic)]
#![crate_type = "lib"]

const MSG: &str = "hello";

const A: () = std::panic!("blåhaj");
//~^ ERROR evaluation of constant value failed

Expand All @@ -14,14 +16,20 @@ const C: () = std::unreachable!();
const D: () = std::unimplemented!();
//~^ ERROR evaluation of constant value failed

const E: () = core::panic!("shark");
const E: () = std::panic!("{}", MSG);
//~^ ERROR evaluation of constant value failed

const A_CORE: () = core::panic!("shark");
//~^ ERROR evaluation of constant value failed

const B_CORE: () = core::panic!();
//~^ ERROR evaluation of constant value failed

const F: () = core::panic!();
const C_CORE: () = core::unreachable!();
//~^ ERROR evaluation of constant value failed

const G: () = core::unreachable!();
const D_CORE: () = core::unimplemented!();
//~^ ERROR evaluation of constant value failed

const H: () = core::unimplemented!();
const E_CORE: () = core::panic!("{}", MSG);
//~^ ERROR evaluation of constant value failed
58 changes: 37 additions & 21 deletions src/test/ui/consts/const-eval/const_panic_2021.stderr
Original file line number Diff line number Diff line change
@@ -1,67 +1,83 @@
error[E0080]: evaluation of constant value failed
--> $DIR/const_panic_2021.rs:5:15
--> $DIR/const_panic_2021.rs:7:15
|
LL | const A: () = std::panic!("blåhaj");
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:5:15
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:7:15
|
= 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:8:15
--> $DIR/const_panic_2021.rs:10:15
|
LL | const B: () = std::panic!();
| ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:8:15
| ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:10:15
|
= 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:11:15
--> $DIR/const_panic_2021.rs:13:15
|
LL | const C: () = std::unreachable!();
| ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:11:15
| ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:13: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:14:15
--> $DIR/const_panic_2021.rs:16:15
|
LL | const D: () = std::unimplemented!();
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:14:15
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $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:17:15
--> $DIR/const_panic_2021.rs:19:15
|
LL | const E: () = core::panic!("shark");
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:17:15
LL | const E: () = std::panic!("{}", MSG);
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:19:15
|
= 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:20:15
--> $DIR/const_panic_2021.rs:22:20
|
LL | const F: () = core::panic!();
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:20:15
LL | const A_CORE: () = core::panic!("shark");
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:22:20
|
= 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:23:15
--> $DIR/const_panic_2021.rs:25:20
|
LL | const G: () = core::unreachable!();
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:23:15
LL | const B_CORE: () = core::panic!();
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:25:20
|
= 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:28:20
|
LL | const C_CORE: () = core::unreachable!();
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:28: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:26:15
--> $DIR/const_panic_2021.rs:31:20
|
LL | const H: () = core::unimplemented!();
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:26:15
LL | const D_CORE: () = core::unimplemented!();
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:31: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
error[E0080]: evaluation of constant value failed
--> $DIR/const_panic_2021.rs:34:20
|
LL | const E_CORE: () = core::panic!("{}", MSG);
| ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:34:20
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 10 previous errors

For more information about this error, try `rustc --explain E0080`.