Skip to content

Commit eb62779

Browse files
Rollup merge of #88954 - nbdd0121:panic3, r=oli-obk
Allow `panic!("{}", computed_str)` in const fn. Special-case `panic!("{}", arg)` and translate it to `panic_display(&arg)`. `panic_display` will behave like `panic_any` in cosnt eval and behave like `panic!(format_args!("{}", arg))` in runtime. This should bring Rust 2015 and 2021 to feature parity in terms of `const_panic`; and hopefully would unblock the stabilisation of #51999. `@rustbot` modify labels: +T-compiler +T-libs +A-const-eval +A-const-fn r? `@oli-obk`
2 parents 723d279 + 11c0e58 commit eb62779

File tree

14 files changed

+129
-40
lines changed

14 files changed

+129
-40
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
3636
let def_id = instance.def_id();
3737
if Some(def_id) == self.tcx.lang_items().panic_fn()
3838
|| Some(def_id) == self.tcx.lang_items().panic_str()
39+
|| Some(def_id) == self.tcx.lang_items().panic_display()
3940
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
4041
{
41-
// &str
42+
// &str or &&str
4243
assert!(args.len() == 1);
4344

44-
let msg_place = self.deref_operand(&args[0])?;
45+
let mut msg_place = self.deref_operand(&args[0])?;
46+
while msg_place.layout.ty.is_ref() {
47+
msg_place = self.deref_operand(&msg_place.into())?;
48+
}
49+
4550
let msg = Symbol::intern(self.read_str(&msg_place)?);
4651
let span = self.find_closest_untracked_caller_location();
4752
let (file, line, col) = self.location_triple_for_span(span);

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+13
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
888888
if is_lang_panic_fn(tcx, callee) {
889889
self.check_op(ops::Panic);
890890

891+
// `begin_panic` and `panic_display` are generic functions that accept
892+
// types other than str. Check to enforce that only str can be used in
893+
// const-eval.
894+
891895
// const-eval of the `begin_panic` fn assumes the argument is `&str`
892896
if Some(callee) == tcx.lang_items().begin_panic_fn() {
893897
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
@@ -896,6 +900,15 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
896900
}
897901
}
898902

903+
// const-eval of the `panic_display` fn assumes the argument is `&&str`
904+
if Some(callee) == tcx.lang_items().panic_display() {
905+
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
906+
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
907+
{}
908+
_ => self.check_op(ops::PanicNonStr),
909+
}
910+
}
911+
899912
return;
900913
}
901914

compiler/rustc_const_eval/src/transform/check_consts/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
7979
// Keep in sync with what that function handles!
8080
Some(def_id) == tcx.lang_items().panic_fn()
8181
|| Some(def_id) == tcx.lang_items().panic_str()
82+
|| Some(def_id) == tcx.lang_items().panic_display()
8283
|| Some(def_id) == tcx.lang_items().begin_panic_fn()
8384
|| Some(def_id) == tcx.lang_items().panic_fmt()
8485
|| Some(def_id) == tcx.lang_items().begin_panic_fmt()

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ language_item_table! {
283283
// a weak lang item, but do not have it defined.
284284
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
285285
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
286+
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
286287
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
287288
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
288289
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,7 @@ symbols! {
923923
panic_2021,
924924
panic_abort,
925925
panic_bounds_check,
926+
panic_display,
926927
panic_fmt,
927928
panic_handler,
928929
panic_impl,

library/core/src/panic.rs

+9
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ pub macro panic_2015 {
2727
($msg:literal $(,)?) => (
2828
$crate::panicking::panic($msg)
2929
),
30+
// Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
3031
($msg:expr $(,)?) => (
3132
$crate::panicking::panic_str($msg)
3233
),
34+
// Special-case the single-argument case for const_panic.
35+
("{}", $arg:expr $(,)?) => (
36+
$crate::panicking::panic_display(&$arg)
37+
),
3338
($fmt:expr, $($arg:tt)+) => (
3439
$crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
3540
),
@@ -44,6 +49,10 @@ pub macro panic_2021 {
4449
() => (
4550
$crate::panicking::panic("explicit panic")
4651
),
52+
// Special-case the single-argument case for const_panic.
53+
("{}", $arg:expr $(,)?) => (
54+
$crate::panicking::panic_display(&$arg)
55+
),
4756
($($t:tt)+) => (
4857
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
4958
),

library/core/src/panicking.rs

+7
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ pub fn panic_str(expr: &str) -> ! {
6060
panic_fmt(format_args!("{}", expr));
6161
}
6262

63+
#[inline]
64+
#[track_caller]
65+
#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics
66+
pub fn panic_display<T: fmt::Display>(x: &T) -> ! {
67+
panic_fmt(format_args!("{}", *x));
68+
}
69+
6370
#[cold]
6471
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
6572
#[track_caller]

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@
258258
#![feature(const_trait_impl)]
259259
#![feature(container_error_extra)]
260260
#![feature(core_intrinsics)]
261+
#![feature(core_panic)]
261262
#![feature(custom_test_frameworks)]
262263
#![feature(decl_macro)]
263264
#![feature(doc_cfg)]

library/std/src/panic.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::thread::Result;
1010

1111
#[doc(hidden)]
1212
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
13-
#[allow_internal_unstable(libstd_sys_internals, const_format_args)]
13+
#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)]
1414
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
1515
#[rustc_macro_transparency = "semitransparent"]
1616
pub macro panic_2015 {
@@ -20,6 +20,10 @@ pub macro panic_2015 {
2020
($msg:expr $(,)?) => ({
2121
$crate::rt::begin_panic($msg)
2222
}),
23+
// Special-case the single-argument case for const_panic.
24+
("{}", $arg:expr $(,)?) => ({
25+
$crate::rt::panic_display(&$arg)
26+
}),
2327
($fmt:expr, $($arg:tt)+) => ({
2428
$crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+))
2529
}),

library/std/src/rt.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

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

2021
// To reduce the generated code of the new `lang_start`, this function is doing
2122
// the real work.

src/test/ui/consts/const-eval/const_panic.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ const Y: () = std::unreachable!();
1515

1616
const X: () = std::unimplemented!();
1717
//~^ ERROR evaluation of constant value failed
18-
//
18+
1919
const W: () = std::panic!(MSG);
2020
//~^ ERROR evaluation of constant value failed
2121

22+
const W2: () = std::panic!("{}", MSG);
23+
//~^ ERROR evaluation of constant value failed
24+
2225
const Z_CORE: () = core::panic!("cheese");
2326
//~^ ERROR evaluation of constant value failed
2427

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

3437
const W_CORE: () = core::panic!(MSG);
3538
//~^ ERROR evaluation of constant value failed
39+
40+
const W2_CORE: () = core::panic!("{}", MSG);
41+
//~^ ERROR evaluation of constant value failed

src/test/ui/consts/const-eval/const_panic.stderr

+27-11
Original file line numberDiff line numberDiff line change
@@ -39,45 +39,61 @@ LL | const W: () = std::panic!(MSG);
3939
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
4040

4141
error[E0080]: evaluation of constant value failed
42-
--> $DIR/const_panic.rs:22:20
42+
--> $DIR/const_panic.rs:22:16
43+
|
44+
LL | const W2: () = std::panic!("{}", MSG);
45+
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:22:16
46+
|
47+
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
48+
49+
error[E0080]: evaluation of constant value failed
50+
--> $DIR/const_panic.rs:25:20
4351
|
4452
LL | const Z_CORE: () = core::panic!("cheese");
45-
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20
53+
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:25:20
4654
|
4755
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
4856

4957
error[E0080]: evaluation of constant value failed
50-
--> $DIR/const_panic.rs:25:21
58+
--> $DIR/const_panic.rs:28:21
5159
|
5260
LL | const Z2_CORE: () = core::panic!();
53-
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21
61+
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:28:21
5462
|
5563
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
5664

5765
error[E0080]: evaluation of constant value failed
58-
--> $DIR/const_panic.rs:28:20
66+
--> $DIR/const_panic.rs:31:20
5967
|
6068
LL | const Y_CORE: () = core::unreachable!();
61-
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20
69+
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:31:20
6270
|
6371
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
6472

6573
error[E0080]: evaluation of constant value failed
66-
--> $DIR/const_panic.rs:31:20
74+
--> $DIR/const_panic.rs:34:20
6775
|
6876
LL | const X_CORE: () = core::unimplemented!();
69-
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20
77+
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:34:20
7078
|
7179
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
7280

7381
error[E0080]: evaluation of constant value failed
74-
--> $DIR/const_panic.rs:34:20
82+
--> $DIR/const_panic.rs:37:20
7583
|
7684
LL | const W_CORE: () = core::panic!(MSG);
77-
| ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20
85+
| ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:37:20
86+
|
87+
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
88+
89+
error[E0080]: evaluation of constant value failed
90+
--> $DIR/const_panic.rs:40:21
91+
|
92+
LL | const W2_CORE: () = core::panic!("{}", MSG);
93+
| ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:40:21
7894
|
7995
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
8096

81-
error: aborting due to 10 previous errors
97+
error: aborting due to 12 previous errors
8298

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

src/test/ui/consts/const-eval/const_panic_2021.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#![feature(const_panic)]
33
#![crate_type = "lib"]
44

5+
const MSG: &str = "hello";
6+
57
const A: () = std::panic!("blåhaj");
68
//~^ ERROR evaluation of constant value failed
79

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

17-
const E: () = core::panic!("shark");
19+
const E: () = std::panic!("{}", MSG);
20+
//~^ ERROR evaluation of constant value failed
21+
22+
const A_CORE: () = core::panic!("shark");
23+
//~^ ERROR evaluation of constant value failed
24+
25+
const B_CORE: () = core::panic!();
1826
//~^ ERROR evaluation of constant value failed
1927

20-
const F: () = core::panic!();
28+
const C_CORE: () = core::unreachable!();
2129
//~^ ERROR evaluation of constant value failed
2230

23-
const G: () = core::unreachable!();
31+
const D_CORE: () = core::unimplemented!();
2432
//~^ ERROR evaluation of constant value failed
2533

26-
const H: () = core::unimplemented!();
34+
const E_CORE: () = core::panic!("{}", MSG);
2735
//~^ ERROR evaluation of constant value failed
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,83 @@
11
error[E0080]: evaluation of constant value failed
2-
--> $DIR/const_panic_2021.rs:5:15
2+
--> $DIR/const_panic_2021.rs:7:15
33
|
44
LL | const A: () = std::panic!("blåhaj");
5-
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:5:15
5+
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:7:15
66
|
77
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
88

99
error[E0080]: evaluation of constant value failed
10-
--> $DIR/const_panic_2021.rs:8:15
10+
--> $DIR/const_panic_2021.rs:10:15
1111
|
1212
LL | const B: () = std::panic!();
13-
| ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:8:15
13+
| ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:10:15
1414
|
1515
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
1616

1717
error[E0080]: evaluation of constant value failed
18-
--> $DIR/const_panic_2021.rs:11:15
18+
--> $DIR/const_panic_2021.rs:13:15
1919
|
2020
LL | const C: () = std::unreachable!();
21-
| ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:11:15
21+
| ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:13:15
2222
|
2323
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
2424

2525
error[E0080]: evaluation of constant value failed
26-
--> $DIR/const_panic_2021.rs:14:15
26+
--> $DIR/const_panic_2021.rs:16:15
2727
|
2828
LL | const D: () = std::unimplemented!();
29-
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:14:15
29+
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:16:15
3030
|
3131
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
3232

3333
error[E0080]: evaluation of constant value failed
34-
--> $DIR/const_panic_2021.rs:17:15
34+
--> $DIR/const_panic_2021.rs:19:15
3535
|
36-
LL | const E: () = core::panic!("shark");
37-
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:17:15
36+
LL | const E: () = std::panic!("{}", MSG);
37+
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:19:15
3838
|
3939
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
4040

4141
error[E0080]: evaluation of constant value failed
42-
--> $DIR/const_panic_2021.rs:20:15
42+
--> $DIR/const_panic_2021.rs:22:20
4343
|
44-
LL | const F: () = core::panic!();
45-
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:20:15
44+
LL | const A_CORE: () = core::panic!("shark");
45+
| ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:22:20
4646
|
4747
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
4848

4949
error[E0080]: evaluation of constant value failed
50-
--> $DIR/const_panic_2021.rs:23:15
50+
--> $DIR/const_panic_2021.rs:25:20
5151
|
52-
LL | const G: () = core::unreachable!();
53-
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:23:15
52+
LL | const B_CORE: () = core::panic!();
53+
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:25:20
54+
|
55+
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
56+
57+
error[E0080]: evaluation of constant value failed
58+
--> $DIR/const_panic_2021.rs:28:20
59+
|
60+
LL | const C_CORE: () = core::unreachable!();
61+
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:28:20
5462
|
5563
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
5664

5765
error[E0080]: evaluation of constant value failed
58-
--> $DIR/const_panic_2021.rs:26:15
66+
--> $DIR/const_panic_2021.rs:31:20
5967
|
60-
LL | const H: () = core::unimplemented!();
61-
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:26:15
68+
LL | const D_CORE: () = core::unimplemented!();
69+
| ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:31:20
6270
|
6371
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
6472

65-
error: aborting due to 8 previous errors
73+
error[E0080]: evaluation of constant value failed
74+
--> $DIR/const_panic_2021.rs:34:20
75+
|
76+
LL | const E_CORE: () = core::panic!("{}", MSG);
77+
| ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:34:20
78+
|
79+
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
80+
81+
error: aborting due to 10 previous errors
6682

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

0 commit comments

Comments
 (0)