Closed
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::unwrap
andOption::unwrap
becomeconst 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)
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
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_panic
lint, and will not compile in Edition 2021. To support usecases like this we would need to makestd::panic::panic_any
aconst fn
too (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_panic
is stabilized: time-rs/time#322rodrimati1992 commentedon May 12, 2021
@jhpratt The code in that issue would not be affected by
catch_unwind
being usable in const contexts, since it stores the validated data in aconst
before 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, wherestr
is a string slicepanic_any
const, 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 fn
would 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
/static
panic such that it can not beallow
ed. I am sympathetic to that idea. The only reason CTFE error can beallow
ed 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.
static_assert!
Rust-for-Linux/linux#26941 remaining items
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_panic
in Rust 2021 starting in 1.56: Make const panic!("..") work in Rust 2021. #86998.panic_str
function works inconst_panic
: Fix const core::panic!(non_literal_str). #78069.In addition, I've heard this idea floating around to make
const_panic
enable 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_panic
is 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)
.