Skip to content

Commit 5a44ed0

Browse files
authored
Merge pull request #2345 from oli-obk/big_bold_letters
Allow panicking in constants
2 parents 89ed46e + 5ee814a commit 5a44ed0

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

text/2345-const-panic.md

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
- Feature Name: `const_panic`
2+
- Start Date: 2018-02-22
3+
- RFC PR: [rust-lang/rfcs#2345](https://github.com/rust-lang/rfcs/pull/2345)
4+
- Rust Issue: [rust-lang/rust#51999](https://github.com/rust-lang/rust/issues/51999)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Allow the use of `panic!`, `assert!` and `assert_eq!` within constants and
10+
report their evaluation as a compile-time error.
11+
12+
# Motivation
13+
[motivation]: #motivation
14+
15+
It can often be desirable to terminate a constant evaluation due to invalid
16+
arguments. Currently there's no way to do this other than to use `Result` to
17+
produce an `Err` in case of errors. Unfortunately this will end up as a runtime
18+
problem and not abort compilation, even though the problem has been detected at
19+
compile-time. There are already ways to abort compilation, e.g. by invoking
20+
`["some assert failed"][42]` within a constant, which will abort with a
21+
compile-time error pointing at the span of the index operation. But this hack is
22+
not very convenient to use and produces the wrong error message.
23+
24+
# Guide-level explanation
25+
[guide-level-explanation]: #guide-level-explanation
26+
27+
You can now use `panic!` and `assert!` within `const fn`s. This means that when
28+
the const fn is invoked at runtime, you will get a regular panic, but if it is
29+
invoked at compile-time, the panic message will show up as an error message.
30+
31+
As an example, imagine a function that converts strings to their corresponding
32+
booleans.
33+
34+
```rust
35+
const fn parse_bool(s: &str) -> bool {
36+
match s {
37+
"true" => true,
38+
"false" => false,
39+
other => panic!("`{}` is not a valid bool"),
40+
}
41+
}
42+
parse_bool("true");
43+
parse_bool("false");
44+
parse_bool("foo");
45+
```
46+
47+
will produce an error with your custom error message:
48+
49+
```
50+
error[E0080]: `foo` is not a valid bool
51+
--> src/main.rs: 5:25
52+
|
53+
5 | other => panic!("`{}` is not a valid bool"),
54+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
55+
note: during the evaluation of
56+
|
57+
10 | parse_bool("foo");
58+
| ^^^^^^^^^^^^^^^^^
59+
```
60+
61+
# Reference-level explanation
62+
[reference-level-explanation]: #reference-level-explanation
63+
64+
MIR interpretation gets a special case for the panic machinery (which isn't
65+
const fn). If the `panic` lang item is entered, instead of producing an error
66+
about it not being const fn, we produce a specialized error with the panic's
67+
message. This panic reporting machinery is already present in the mir
68+
interpreter, but needs the lang item detection in order to work.
69+
70+
Note that this internal machinery is inherently unstable and thus never
71+
invoked directly by users. Users will use the `panic!` macro as an entry point.
72+
The internal details of the panic handling might change in the future, but always
73+
in a way that will keep allowing MIR interpretation to evaluate it. All future
74+
changes will have to address this directly and regression tests should ensure
75+
that we never break the const evaluability.
76+
77+
# Drawbacks
78+
[drawbacks]: #drawbacks
79+
80+
We have to implement some magic around processing `fmt::Arguments` objects and
81+
producing the panic message from that.
82+
83+
# Rationale and alternatives
84+
[alternatives]: #alternatives
85+
86+
* We could add a special constant error reporting mechanism. This has the
87+
disadvantage of widening the gap between const eval and runtime execution.
88+
* We could make `String` and formatting const enough to allow the panic
89+
formatting machinery to be interpreted and made const fn
90+
* Don't produce a good error message, just say "const eval encountered an error"
91+
and point the user to the panic location. This already works out of the box
92+
right now. We can improve the error message in the future with the `String` +
93+
formatting alternative. This is the most minimalistic alternative to this RFC
94+
95+
# Unresolved questions
96+
[unresolved]: #unresolved-questions
97+
98+
* Should there be some additional message in the error about this being a panic
99+
turned error? Or do we just produce the exact message the panic would produce?
100+
101+
* This change becomes really useful if `Result::unwrap` and `Option::unwrap`
102+
become const fn, doing both in one go might be a good idea

0 commit comments

Comments
 (0)