@@ -115,56 +115,10 @@ expressions are actually eligible for promotion? We refer to eligible
115115expressions as "promotable" and describe the restrictions on such expressions
116116below.
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
271225the 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