Repository navigation
Stabilize RFC 2345: Allow panicking in constants #85194
Copy link
Copy link
Closed
Labels
T-langRelevant to the language teamRelevant to the language team
Description
Stabilization report
🛑 Issue with Rust 2021 🛑
Stabilization is currently blocked on resolving how this works with Rust 2021
Summary
This feature allows panicking within constants and reporting a custom message as a compile-time error.
The following code will become valid on stable:
const fn foo(val: u8) {
assert!(val == 1, "val is not 1");
}
const MSG: &str = "custom message";
const _: () = std::panic!(MSG);
const _: () = panic!("custom message");The message looks like:
error: any use of this value will cause an error
--> src/main.rs:4:15
|
4 | const _: () = std::panic!(MSG);
| --------------^^^^^^^^^^^^^^^^-
| |
| the evaluated program panicked at 'custom message', src/main.rs:4:15
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Motivation for this RFC can be found here: https://rust-lang.github.io/rfcs/2345-const-panic.html#motivation
More examples can be found here: https://github.com/rust-lang/rust/blob/673d0db5e393e9c64897005b470bfeb6d5aec61b/src/test/ui/consts/const-eval/const_panic.rs
Edge cases & tests
- https://github.com/rust-lang/rust/blob/673d0db5e393e9c64897005b470bfeb6d5aec61b/src/test/ui/consts/const-eval/panic-never-type.rs
- https://github.com/rust-lang/rust/blob/673d0db5e393e9c64897005b470bfeb6d5aec61b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
- https://github.com/rust-lang/rust/blob/673d0db5e393e9c64897005b470bfeb6d5aec61b/src/test/ui/consts/issue-66693.rs
- https://github.com/rust-lang/rust/blob/673d0db5e393e9c64897005b470bfeb6d5aec61b/src/test/ui/consts/control-flow/short-circuit-let.rs
Some questions which should be resolved in the future
We have some "unresolved questions" but they aren't an actual blocker.
- Should there be some additional message in the error about this being a panic turned error?
Or do we just produce the exact message the panic would produce? - This change becomes really useful if
Result::unwrapandOption::unwrapbecomeconst fn, doing both in one go might be a good idea.
See the brief summary comment here: #51999 (comment)
Originally posted by @JohnTitor in #51999 (comment)
Reacted by Yuki Okushi, Alex Crawford, Erich Gubler, Alex Martens, Alexander Huszagh, Vincent Isambart, Aaron Hill, Wesley Wiser, Élie ROUDNINSKI, Kolsky and 1 more
Reacted by Lu, Wangshan, Wesley Wiser, Joe Richey, Élie ROUDNINSKI, Kolsky and Benjamin Bouvier
Reacted by Erich Gubler, Wesley Wiser, Jon Gjengset, Élie ROUDNINSKI and Kolsky
Metadata
Metadata
Assignees
Labels
T-langRelevant to the language teamRelevant to the language team
Activity
Aaron1011 commentedon May 11, 2021
One additional unresolved question that @RalfJung had brought up previously - do we ever want to allow catching panics in constants? The only issue I can think of would be users expecting
panic!()to always abort compilation - but users should be aware that panics can be caught, especially if they're writing aconst fn, which can also be called at runtime.nikomatsakis commentedon May 11, 2021
Is the question really about whether we want to allow catching panics in constants?
Aaron1011 commentedon May 11, 2021
IIRC, the original question was about whether
panic!()is compatible with later deciding we want to allow catching panics in constants.Nemo157 commentedon May 11, 2021
This specific example triggers the
non_fmt_paniclint, and will not compile in Edition 2021. To support usecases like this we would need to makestd::panic::panic_anyaconst fntoo (or get support for traits-in-const to allow using the format machinery).nikomatsakis commentedon May 11, 2021
@Aaron1011 so in other words, the question is, will someone write a constant that panics and assumes that this panic aborts compilation in some crucial way, but then we introduce a wrapper that captures the panic, and now the safety guarantee is not upheld?
jhpratt commentedon May 11, 2021
Personally I'd like to be able to panic in a const context to perform data validation from a macro. This would allow me to eliminate a procedural macro. If a const panic could be caught, that would effectively eliminate the ability to validate data (I think, feel free to correct me).
Reference to what I hope will be possible once
const_panicis stabilized: time-rs/time#322rodrimati1992 commentedon May 12, 2021
@jhpratt The code in that issue would not be affected by
catch_unwindbeing usable in const contexts, since it stores the validated data in aconstbefore returning it.CodesInChaos commentedon May 12, 2021
@Nemo157 In my comment on the original issue I proposed other options, which might be easier to implement:
panic!("{}", str)work, wherestris a string slicepanic_anyconst, but only if the argument is a string slice.nikomatsakis commentedon May 13, 2021
I'd like an example where there is a panic that should abort compilation but catching it would produce a problem -- it feels like the panic erases the const value being produced, so I'm not clear on what kind of error would be swallowed that would be a problem.
RalfJung commentedon May 13, 2021
@Aaron1011 wrote
I am confused -- yes we do want to allow panicking in constants...?
EDIT: Oh, I guess you forgot a "catch" somewhere... could you edit the text? Looks like I am not the only one who got confused. ;)
RalfJung commentedon May 13, 2021
I guess if a
const fnwould perform some validation and then return(), if you can catch panics you can circumvent this validation.But I don't see how this would be any more problematic at compile-time than it is at run-time.
RalfJung commentedon May 13, 2021
Another question that came up is if we should change the error that is emitted when a
const/staticpanic such that it can not beallowed. I am sympathetic to that idea. The only reason CTFE error can beallowed at all is backwards compatibility, and there is no such concern with panics.nikomatsakis commentedon May 13, 2021
I see. I definitely think it should be a hard error.
lachlansneff commentedon May 16, 2021
Are
unwrapandexpectgoing to be stabilized at the same time as this?RalfJung commentedon May 16, 2021
Option::unwrapcan be stabilized; the others require parts of theformat!machinery that are not const-compatible (they will be, eventually, but that'll require a lot of other infrastructure first).28 remaining items
Auto merge of rust-lang#86655 - jonas-schievink:const-arguments-as-st…
nbdd0121 commentedon Jul 4, 2021
Is it possible to special-case Rust 2021
panic!("{}", expr)to mean Rust 2015panic!(expr)?m-ou-se commentedon Jul 5, 2021
@nbdd0121 Those are not the same:
panic!("{}", 123);throws aStringcontaining"123".panic!(123)throws ani32with the value123.panic!("{}", &some_temporary)is valid, whilepanic!(&some_temporary)is not.We can make
panic_any(expr)work in constants, but that function only exists in std, not in core.clarfonthey commentedon Sep 6, 2021
So, I see that there are a lot of blockers on the 2021-edition-style panicking, but I don't actually know what the plan is for this. Got lead here from the tracking issue for #53188, which is blocked on this but still open.
Is the plan to just never allow panicking in const functions, ever? That seems wrong. Are we blocking it on const trait impls to ensure that arbitrary
panic!can be const? It seems like closing this issue without pointing to a replacement is a bit confusing.jhpratt commentedon Sep 6, 2021
Personally I'd like to see const panic with only string literals supported — this would permit things along the lines of (debug) assertions so long as a custom message is provided. Something is better than nothing.
clarfonthey commentedon Sep 6, 2021
I should add that @m-ou-se opened #78356 to help make the literal-only case identical on 2021 edition, which is mostly the primary blocker.
m-ou-se commentedon Sep 6, 2021
@clarfonthey There's multiple ways forward:
panic!("literal")already works withconst_panicin Rust 2021 starting in 1.56: Make const panic!("..") work in Rust 2021. #86998.panic_strfunction works inconst_panic: Fix const core::panic!(non_literal_str). #78069.In addition, I've heard this idea floating around to make
const_panicenable some kind of-Z unleash-the-miri-inside-of-you-like thing onpanic!(). (cc @oli-obk) The idea is that since compilation is going to fail/panic anyway, the compiler doesn't have to follow the strict const evaluation rules anymore and can just try to evaluate anything to try to generate the full panic message, regardless of if Display implementations etc. were marked asconst. (Miri can already evaluate pretty much all of them, as long as they don't open files etc.)jhpratt commentedon Sep 6, 2021
Still unstably by the looks of it? playground
Just asking for clarity purposes because your wording makes it sound like that subset has been stabilized.
m-ou-se commentedon Sep 6, 2021
Yes, gated behind
const_panic, like all const panic, yes.m-ou-se commentedon Sep 6, 2021
@clarfonthey Note that this issue was just for the stabilization report.
The tracking issue for
const_panicis here, and still open and active: #51999clarfonthey commentedon Sep 6, 2021
Oh! That makes a lot of sense now.
CodesInChaos commentedon Sep 6, 2021
I'd like to see at least
panic!(literal)stabilized as soon as possible. I believe that case has no open concerns, and it's already much clearer than the index-out-of-bounds hacks people use at the moment.nbdd0121 commentedon Sep 7, 2021
The issue is that we want all code that works in Rust 2018 to work (or auto-fixed to working code) in Rust 2021. If we stablise
panic!(literal), thenpanic!("{}")works in Rust 2018 but not work in Rust 2021. I see three options here for the MVP:panic!("{{}}")instead ofpanic!("{}", "{}").panic!(literal)in Rust 2018 if literal doesn't contain '{' and '}'.panic!("{}", literal)to same aspanic!(escaped_liteal).