Skip to content

Commit e2ec55a

Browse files
committed
reorder promotion clauses and adjust const-use
1 parent 61db5dc commit e2ec55a

File tree

1 file changed

+57
-50
lines changed

1 file changed

+57
-50
lines changed

promotion.md

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -115,56 +115,10 @@ expressions are actually eligible for promotion? We refer to eligible
115115
expressions as "promotable" and describe the restrictions on such expressions
116116
below.
117117

118-
### Named locals
119-
120-
Promotable expressions cannot refer to named locals. This is not a technical
121-
limitation with the CTFE engine. While writing `let x = {expr}` outside of a
122-
const context, the user likely expects that `x` will live on the stack and be
123-
initialized at run-time. Although this is not (to my knowledge) guaranteed by
124-
the language, we do not wish to violate the user's expectations here.
125-
126-
However, constant-folding still applies: the optimizer may compute `x` at
127-
compile-time and even inline it everywhere if it can show that this does not
128-
observably alter program behavior. Promotion is very different from
129-
constant-folding as promotion can introduce observable differences in behavior
130-
(if const-evaluation fails) and as it is *guaranteed* to happen in some cases
131-
(and thus exploited by the borrow checker).
132-
133-
### Single assignment
134-
135-
We only promote temporaries that are assigned to exactly once. For example, the
136-
lifetime of the temporary whose reference is assigned to `x` below will not be
137-
extended.
138-
139-
```rust
140-
let x: &'static i32 = &if cfg!(windows) { 0 } else { 1 };
141-
```
142-
143-
Once again, this is not a fundamental limitation in the CTFE engine; we are
144-
perfectly capable of evaluating such expressions at compile time. However,
145-
determining the promotability of complex expressions would require more
146-
resources for little benefit.
147-
148-
### Access to a `const` or `static`
149-
150-
When accessing a `const` in a promotable context, the initializer of that body
151-
is not subject to any restrictions. However, the usual restrictions on the
152-
*result* of that computation still apply: it [cannot be `Drop`](#drop).
153-
154-
For instance, while the previous example was not legal, the following would be:
155-
156-
```rust
157-
const BOOL: i32 = {
158-
let ret = if cfg!(windows) { 0 } else { 1 };
159-
ret
160-
};
161-
162-
let x: &'static i32 = &BOOL;
163-
```
164-
165-
An access to a `static` is only promotable within the initializer of another
166-
`static`. This is for the same reason that `const` initializers
167-
[cannot access statics](const.md#reading-statics).
118+
First of all, expressions have to be [allowed in constants](const.md). The
119+
restrictions described there are needed because we want `const` to behave the
120+
same as copying the `const` initializer everywhere the constant is used; we need
121+
the same property when promoting expressions. But we need more.
168122

169123
### Panics
170124

@@ -270,6 +224,59 @@ or `const` item and refer to that.
270224
*Dynamic check.* The Miri engine could dynamically check this by ensuring that
271225
the result of computing a promoted is a value that does not need dropping.
272226

227+
### Access to a `const` or `static`
228+
229+
When accessing a `const` in a promotable context, its value anyway gets computed
230+
at compile-time, so we do not have to check the initializer. However, the
231+
restrictions described above still apply for the *result* of the promoted
232+
computation: in particular, it must be a valid `const` (i.e., it cannot
233+
introduce interior mutability) and it must not require dropping.
234+
235+
For instance, while the previous example was not legal, the following would be:
236+
237+
```rust
238+
const BOOL: i32 = {
239+
let ret = if cfg!(windows) { 0 } else { 1 };
240+
ret
241+
};
242+
243+
let x: &'static i32 = &BOOL;
244+
```
245+
246+
An access to a `static` is only promotable within the initializer of another
247+
`static`. This is for the same reason that `const` initializers
248+
[cannot access statics](const.md#reading-statics).
249+
250+
### Named locals
251+
252+
Promotable expressions cannot refer to named locals. This is not a technical
253+
limitation with the CTFE engine. While writing `let x = {expr}` outside of a
254+
const context, the user likely expects that `x` will live on the stack and be
255+
initialized at run-time. Although this is not (to my knowledge) guaranteed by
256+
the language, we do not wish to violate the user's expectations here.
257+
258+
However, constant-folding still applies: the optimizer may compute `x` at
259+
compile-time and even inline it everywhere if it can show that this does not
260+
observably alter program behavior. Promotion is very different from
261+
constant-folding as promotion can introduce observable differences in behavior
262+
(if const-evaluation fails) and as it is *guaranteed* to happen in some cases
263+
(and thus exploited by the borrow checker).
264+
265+
### Single assignment
266+
267+
We only promote temporaries that are assigned to exactly once. For example, the
268+
lifetime of the temporary whose reference is assigned to `x` below will not be
269+
extended.
270+
271+
```rust
272+
let x: &'static i32 = &if cfg!(windows) { 0 } else { 1 };
273+
```
274+
275+
Once again, this is not a fundamental limitation in the CTFE engine; we are
276+
perfectly capable of evaluating such expressions at compile time. However,
277+
determining the promotability of complex expressions would require more
278+
resources for little benefit.
279+
273280
## Open questions
274281

275282
* There is a fourth kind of CTFE failure -- resource exhaustion. What do we do

0 commit comments

Comments
 (0)