Skip to content

Commit c95bbf4

Browse files
committed
improve/update panic section
1 parent dbfeb35 commit c95bbf4

File tree

1 file changed

+23
-23
lines changed

1 file changed

+23
-23
lines changed

promotion.md

+23-23
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,12 @@ should not have promoted something, but then it is already too late -- and the
119119
dynamic checks for that are exactly the ones we are already doing for constants
120120
and statics.
121121

122-
### Panics
122+
### Panics, overflow and bounds checks
123123

124-
Promotion is not allowed to throw away side effects. This includes panicking.
125-
Let us look at what happens when we promote `&(0_usize - 1)` in a debug build:
126-
We have to avoid erroring at compile-time, because that would be promotion
127-
breaking compilation, but we must be sure to error correctly at run-time. In
128-
the MIR, this looks roughly like
124+
Let us look at what happens when we promote `&(0_usize - 1)` in a debug build.
125+
This code is promoted even though we cannot promote code that could fail, and
126+
this code will fail with an overflow error! What is happening? We have to look
127+
at the underlying MIR representation of this code to explain what happens:
129128

130129
```
131130
_tmp1 = CheckedSub (const 0usize) (const 1usize)
@@ -137,26 +136,27 @@ _res = &_tmp2
137136
```
138137

139138
Both `_tmp1` and `_tmp2` are promoted. `_tmp1` evaluates to `(~0, true)`, so
140-
the assertion will always fail at run-time. Computing `_tmp2` fails with a
141-
panic, which is thrown away -- so we have no result. In principle, we could
142-
generate any code for this because we know the code is unreachable (the
143-
assertion is going to fail). Just to be safe, we generate a call to
144-
`llvm.trap`.
145-
146-
As long as CTFE only panics when run-time code would also have panicked, this
147-
works out correctly: The MIR already contains provisions for what to do on
148-
panics (unwind edges etc.), so when CTFE panics we can generate code that
149-
hard-codes a panic to happen at run-time. In other words, *promotion relies on
150-
CTFE correctly implementing both normal program behavior and panics*. An
151-
earlier version of miri used to panic on arithmetic overflow even in release
152-
mode. This breaks promotion, because now promoting code that would work (and
153-
could not panic!) at run-time leads to a compile-time CTFE error.
139+
the assertion will always fail at run-time. Computing `_tmp2` evaluates to `~0`.
140+
141+
In other words, the actually failing check is not promoted, only the computation
142+
that serves as input to the check is promoted.
143+
144+
An earlier version of Miri used to error on arithmetic overflow even in release
145+
mode. This breaks promotion, because now promoting code like `_tmp1` would
146+
introduce promotes that fail to evaluate, which is not acceptable as explained
147+
above!
148+
149+
Something similar but more subtle happens when promoting array accesses: the
150+
bounds check is not promoted, but the array access is. However, before accepting
151+
a temporary for promotion, we ensure that array accesses are definitely
152+
in-bounds. This leads to MIR without bounds checks, but we know the array access
153+
will always succeed.
154154

155155
### Const safety
156156

157-
We have explained what happens when evaluating a promoted panics, but what about
158-
other kinds of failure -- what about hitting an unsupported operation or
159-
undefined behavior? To make sure this does not happen, only const safe code
157+
We have explained how we ensure that evaluating a promoted does not panic, but
158+
what about other kinds of failure -- what about hitting an unsupported operation
159+
or undefined behavior? To make sure this does not happen, only const safe code
160160
gets promoted. The exact details for `const safety` are discussed in
161161
[here](const_safety.md).
162162

0 commit comments

Comments
 (0)