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

Make const panic!("..") work in Rust 2021. #86998

Merged
merged 9 commits into from
Jul 29, 2021

Conversation

m-ou-se
Copy link
Member

@m-ou-se m-ou-se commented Jul 9, 2021

During const eval, this replaces calls to core::panicking::panic_fmt and std::panicking::being_panic_fmt with a call to a new const fn: core::panicking::const_panic_fmt. That function uses fmt::Arguments::as_str() to get the str and calls panic_str with that instead.

panic!() invocations with formatting arguments are still not accepted, as the creation of such a fmt::Arguments cannot be done in constant functions right now.

r? @RalfJung

@m-ou-se m-ou-se added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) labels Jul 9, 2021
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 9, 2021
@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

A small problem with this is that the panic is now reported inside core instead of at the point where the panic macro is invoked:

error[E0080]: evaluation of constant value failed
   --> /home/mara/rust/library/core/src/panicking.rs:102:9
    |
102 |         panic_str(msg);
    |         ^^^^^^^^^^^^^^
    |         |
    |         the evaluated program panicked at 'hello', src/main.rs:4:5
    |         inside `core::panicking::panic_fmt` at /home/mara/rust/library/core/src/panicking.rs:102:9
    | 
   ::: src/main.rs:4:5
    |
4   |     panic!("hello")
    |     --------------- inside `hey` at /home/mara/rust/library/core/src/panic.rs:38:9
...
7   | const X: u32 = hey();
    |                ----- inside `X` at src/main.rs:7:16

Maybe const eval should use #[track_caller] too.

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Hm, looks like that should already work:

let span = self.find_closest_untracked_caller_location();

Trying to figure out what goes wrong now.

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Ah, that's just used for the message, which is correct:

the evaluated program panicked at 'hello', src/main.rs:4:5

But maybe it should be used for the span to point the error at too.

@rust-log-analyzer

This comment has been minimized.

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Fixed in #87000

Marking this as blocked on that.

@m-ou-se m-ou-se added the S-blocked Status: Blocked on something else such as an RFC or other implementation work. label Jul 9, 2021
@m-ou-se m-ou-se force-pushed the const-panic-fmt-as-str branch from 0dc0cf7 to 5a8d2a8 Compare July 9, 2021 13:35
library/core/src/panicking.rs Outdated Show resolved Hide resolved
@rust-log-analyzer

This comment has been minimized.

Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have existing tests that ensure that format_args! cannot be called in const contexts? Just to make sure we don't accidentally allow things due to the various allow_internal_unstable on these macros.

compiler/rustc_mir/src/const_eval/machine.rs Outdated Show resolved Hide resolved
@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

The test is failing now, but will pass once #87000 is merged.

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

do we have existing tests that ensure that format_args! cannot be called in const contexts? Just to make sure we don't accidentally allow things due to the various allow_internal_unstable on these macros.

This change will indeed allow format_args!("something") in const functions. Not sure how to avoid that other than by adding a new format_args_const macro. I can add a rustc_const_unstable attribute with a new feature name to fmt::Arguments::new*, but I can't only activate that in format_args!() inside panic!() and not in just format_args!() by itself.

@RalfJung
Copy link
Member

RalfJung commented Jul 9, 2021

How does this MR relate to #86830? They seem to try to solve the same problem...?

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Oh, didn't see that one yet. Looking now.

@oli-obk
Copy link
Contributor

oli-obk commented Jul 9, 2021

How does this MR relate to #86830? They seem to try to solve the same problem...?

fixes the same problem, but the solution is more maintainable I believe.

This change will indeed allow format_args!("something") in const functions. Not sure how to avoid that other than by adding a new format_args_const macro. I can add a rustc_const_unstable attribute with a new feature name to fmt::Arguments::new*, but I can't only activate that in format_args!() inside panic!() and not in just format_args!() by itself.

I think it should work by adding rustc_const_unstable to the newly const functions and use a feature gate name other than fmt_internals. Or does allow_internal_unstable not permit this kind of scheme (adding it to panic! only, even if the usage is in format_args!?

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Or does allow_internal_unstable not permit this kind of scheme (adding it to panic! only, even if the usage is in format_args!?

Nope :(

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Looks like #86830 does the exact same, but in a different way. It also has the same problem of making format_args!("something") const.

@oli-obk
Copy link
Contributor

oli-obk commented Jul 9, 2021

Or does allow_internal_unstable not permit this kind of scheme (adding it to panic! only, even if the usage is in format_args!?

Nope :(

Oh... and we can't fix that, because any fix would then also allow user-expressions in the macro arguments to use the unstable things. So I guess we'd need @eddyb's solution and have a separate-but-equal forever-unstable const_format_args that panic uses internally.

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Oh... and we can't fix that, because any fix would then also allow user-expressions in the macro arguments to use the unstable things. So I guess we'd need @eddyb's solution and have a separate-but-equal forever-unstable const_format_args that panic uses internally.

Yeah. Did that now.

@rust-log-analyzer

This comment has been minimized.

#![feature(const_panic)]
#![crate_type = "lib"]

const A: () = std::panic!("blåhaj");
Copy link
Contributor

@oli-obk oli-obk Jul 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... if my understanding is right, std::panic!(SOME_CONST) does not work anymore in 2021, does your change permit panic!("{}", some_str) to work? If so, that should have a test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof, our test suite is really subpar. We have zero tests for

const FOO: () = {
    let mut x = [4, 2];
    for i in 0..x.len() {
         x[i] = x[i] + b'0';
    }
    let z = unsafe { std::str::from_utf8_unchecked(&x) };
    panic!("{}", z);
};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... if my understanding is right, std::panic!(SOME_CONST) does not work anymore in 2021, does your change permit panic!("{}", some_str) to work?

Nope. I want to make a next PR that makes panic!("{}", "literal") work. panic!("{}", some_str_var) will be a step further into the future.

@rust-log-analyzer

This comment has been minimized.

@m-ou-se m-ou-se force-pushed the const-panic-fmt-as-str branch from 7caa172 to 3d260ff Compare July 9, 2021 15:40
@rust-log-analyzer

This comment has been minimized.

@RalfJung
Copy link
Member

RalfJung commented Jul 9, 2021

So I guess we'd need @eddyb's solution and have a separate-but-equal forever-unstable const_format_args that panic uses internally.

Why that? As I suggested in the other PR, the const checking code could accept format_args! *if it is the argument of a panic!, and reject otherwise.

That seems like a less ugly alternative than a 2nd macro.^^

@m-ou-se
Copy link
Member Author

m-ou-se commented Jul 9, 2021

Or we could just do an FCP to start allowing format_args!("literal") in const context.

@bors
Copy link
Contributor

bors commented Jul 13, 2021

☔ The latest upstream changes (presumably #86857) made this pull request unmergeable. Please resolve the merge conflicts.

m-ou-se and others added 9 commits July 28, 2021 16:10
During const eval, this replaces calls to core::panicking::panic_fmt and
std::panicking::being_panic_fmt with a call to a new const fn:
core::panicking::const_panic_fmt. That function uses
fmt::Arguments::as_str() to get the str and calls panic_str with that
instead.

panic!() invocations with formatting arguments are still not accepted,
as the creation of such a fmt::Arguments cannot be done in constant
functions right now.
@m-ou-se m-ou-se force-pushed the const-panic-fmt-as-str branch from 239ae27 to 312bf8e Compare July 28, 2021 14:19
@m-ou-se m-ou-se linked an issue Jul 28, 2021 that may be closed by this pull request
@oli-obk
Copy link
Contributor

oli-obk commented Jul 28, 2021

Just gonna keep repeating this everywhere, our const panic tests are really underwhelming, we should write more.

That does not block this PR tho, so

r? @oli-obk

@bors r+

@bors
Copy link
Contributor

bors commented Jul 28, 2021

📌 Commit 312bf8e has been approved by oli-obk

@rust-highfive rust-highfive assigned oli-obk and unassigned RalfJung Jul 28, 2021
@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 28, 2021
@bors
Copy link
Contributor

bors commented Jul 29, 2021

⌛ Testing commit 312bf8e with merge 6e0a8bf...

@bors
Copy link
Contributor

bors commented Jul 29, 2021

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing 6e0a8bf to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Jul 29, 2021
@bors bors merged commit 6e0a8bf into rust-lang:master Jul 29, 2021
@rustbot rustbot added this to the 1.56.0 milestone Jul 29, 2021
@m-ou-se m-ou-se deleted the const-panic-fmt-as-str branch July 29, 2021 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The 2021 panic macro no longer works in const functions
8 participants