Skip to content

Stabilize RFC 2345: Allow panicking in constants #85194

Closed
@nikomatsakis

Description

@nikomatsakis
Contributor

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

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 and Option::unwrap become const 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)

Activity

Aaron1011

Aaron1011 commented on May 11, 2021

@Aaron1011
Member

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 a const fn, which can also be called at runtime.

nikomatsakis

nikomatsakis commented on May 11, 2021

@nikomatsakis
ContributorAuthor

Is the question really about whether we want to allow catching panics in constants?

Aaron1011

Aaron1011 commented on May 11, 2021

@Aaron1011
Member

IIRC, the original question was about whether panic!() is compatible with later deciding we want to allow catching panics in constants.

Nemo157

Nemo157 commented on May 11, 2021

@Nemo157
Member
const MSG: &str = "custom message";
const _: () = std::panic!(MSG);

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 make std::panic::panic_any a const fn too (or get support for traits-in-const to allow using the format machinery).

nikomatsakis

nikomatsakis commented on May 11, 2021

@nikomatsakis
ContributorAuthor

@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

jhpratt commented on May 11, 2021

@jhpratt
Member

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#322

rodrimati1992

rodrimati1992 commented on May 12, 2021

@rodrimati1992
Contributor

@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 a const before returning it.

CodesInChaos

CodesInChaos commented on May 12, 2021

@CodesInChaos

@Nemo157 In my comment on the original issue I proposed other options, which might be easier to implement:

  1. make formatting work for string slice arguments, without relying on formatting traits
  2. make the precise pattern panic!("{}", str) work, where str is a string slice
  3. make panic_any const, but only if the argument is a string slice.
nikomatsakis

nikomatsakis commented on May 13, 2021

@nikomatsakis
ContributorAuthor

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

RalfJung commented on May 13, 2021

@RalfJung
Member

@Aaron1011 wrote

One additional unresolved question that @RalfJung had brought up previously - do we ever want to allow panicking in constants?

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

RalfJung commented on May 13, 2021

@RalfJung
Member

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.

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

RalfJung commented on May 13, 2021

@RalfJung
Member

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 be allowed. I am sympathetic to that idea. The only reason CTFE error can be allowed at all is backwards compatibility, and there is no such concern with panics.

nikomatsakis

nikomatsakis commented on May 13, 2021

@nikomatsakis
ContributorAuthor

I see. I definitely think it should be a hard error.

41 remaining items

clarfonthey

clarfonthey commented on Sep 6, 2021

@clarfonthey
Contributor

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

jhpratt commented on Sep 6, 2021

@jhpratt
Member

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

clarfonthey commented on Sep 6, 2021

@clarfonthey
Contributor

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

m-ou-se commented on Sep 6, 2021

@m-ou-se
Member

@clarfonthey There's multiple ways forward:

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 on panic!(). (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 as const. (Miri can already evaluate pretty much all of them, as long as they don't open files etc.)

jhpratt

jhpratt commented on Sep 6, 2021

@jhpratt
Member
  • panic!("literal") already works in Rust 2021 starting in 1.56:

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

m-ou-se commented on Sep 6, 2021

@m-ou-se
Member

Yes, gated behind const_panic, like all const panic, yes.

m-ou-se

m-ou-se commented on Sep 6, 2021

@m-ou-se
Member

@clarfonthey Note that this issue was just for the stabilization report.

The tracking issue for const_panic is here, and still open and active: #51999

clarfonthey

clarfonthey commented on Sep 6, 2021

@clarfonthey
Contributor

Oh! That makes a lot of sense now.

CodesInChaos

CodesInChaos commented on Sep 6, 2021

@CodesInChaos

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

nbdd0121 commented on Sep 7, 2021

@nbdd0121
Contributor

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.

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), then panic!("{}") works in Rust 2018 but not work in Rust 2021. I see three options here for the MVP:

  • Change the lint to suggest panic!("{{}}") instead of panic!("{}", "{}").
  • Only const-stablise panic!(literal) in Rust 2018 if literal doesn't contain '{' and '}'.
  • Treat panic!("{}", literal) to same as panic!(escaped_liteal).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Nemo157@nikomatsakis@joshtriplett@CodesInChaos@RalfJung

        Issue actions

          Stabilize RFC 2345: Allow panicking in constants · Issue #85194 · rust-lang/rust