You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rather than talking about lifetime-extended temporaries in the
top-level scope of an initializer, which is maybe a bit ambiguous,
let's speak directly to the result of the lifetime extension, which is
that these temporaries disallowed for borrows would have their
lifetimes extended to the end of the program.
Let's also speak about place expressions, rather than places, as
that's more precise here.
We'll add examples throughout. Thanks to RalfJ for the substance of
many of these.
operators used on integer and floating point types, `bool`, and `char`.
82
82
83
83
r[const-eval.const-expr.borrows]
84
-
* All forms of [borrow]s, including raw borrows, with one limitation:
85
-
mutable borrows and shared borrows to values with interior mutability
86
-
are not allowed to refer to [lifetime-extended temporaries in the top-level scope of a `const` or `static` initializer expression][lifetime-extension-const].
87
-
88
-
In other words, they are only allowed to refer to *transient* places, to *indirect* places, or to *static* places.
89
-
A place is *transient* if it is based on a local variable whose lifetime is strictly contained inside the current [const context].
90
-
A place is *indirect* if it is based on a [dereference expression][dereference operator].
91
-
A place is *static* if it is based on a `static` item or a [promoted expression].
84
+
* All forms of [borrow]s, including raw borrows, except borrows of expressions whose temporary scopes would be extended (see [temporary lifetime extension]) to the end of the program and which are either:
85
+
* Mutable borrows.
86
+
* Shared borrows of expressions that result in values with [interior mutability].
87
+
88
+
```rust,compile_fail,E0764
89
+
// Due to being in tail position, this borrow extends the scope of the
90
+
// temporary to the end of the program. Since the borrow is mutable,
91
+
// this is not allowed in a const expression.
92
+
const C: &u8 = &mut 0; // ERROR not allowed
93
+
```
94
+
95
+
```rust,compile_fail,E0764
96
+
// Const blocks are similar to initializers of `const` items.
97
+
let _: &u8 = const { &mut 0 }; // ERROR not allowed
98
+
```
99
+
100
+
```rust,compile_fail,E0492
101
+
# use core::sync::atomic::AtomicU8;
102
+
// This is not allowed as 1) the temporary scope is extended to the
103
+
// end of the program and 2) the temporary has interior mutability.
104
+
const C: &AtomicU8 = &AtomicU8::new(0); // ERROR not allowed
105
+
```
106
+
107
+
```rust,compile_fail,E0492
108
+
# use core::sync::atomic::AtomicU8;
109
+
// As above.
110
+
let _: &_ = const { &AtomicU8::new(0) }; // ERROR not allowed
111
+
```
112
+
113
+
```rust
114
+
# #![allow(static_mut_refs)]
115
+
// Even though this borrow is mutable, it's not of a temporary, so
116
+
// this is allowed.
117
+
constC:&u8=unsafe { staticmutS:u8=0; &mutS }; // OK
118
+
```
119
+
120
+
```rust
121
+
# usecore::sync::atomic::AtomicU8;
122
+
// Even though this borrow is of a value with interior mutability,
123
+
// it's not of a temporary, so this is allowed.
124
+
constC:&AtomicU8= {
125
+
staticS:AtomicU8=AtomicU8::new(0); &S// OK
126
+
};
127
+
```
128
+
129
+
```rust
130
+
# usecore::sync::atomic::AtomicU8;
131
+
// This shared borrow of an interior mutable temporary is allowed
132
+
// because its scope is not extended.
133
+
constC: () = { _=&AtomicU8::new(0); }; // OK
134
+
```
135
+
136
+
```rust
137
+
// Even though the borrow is mutable and the temporary lives to the
138
+
// end of the program due to promotion, this is allowed because the
139
+
// borrow is not in tail position and so the scope of the temporary
140
+
// is not extended via temporary lifetime extension.
> In other words -- to focus on what's allowed rather than what's not allowed -- shared borrows of interior mutable data and mutable borrows are only allowed in a [const context] when the borrowed [place expression] is *transient*, *indirect*, or *static*.
148
+
>
149
+
> A place expression is *transient* if it is a variable local to the current const context or an expression whose temporary scope is contained inside the current const context.
150
+
>
151
+
> ```rust
152
+
> // The borrow is of a variable local to the initializer, therefore
153
+
> // this place expresssion is transient.
154
+
> constC: () = { letmutx=0; _=&mutx; };
155
+
> ```
156
+
>
157
+
> ```rust
158
+
> // The borrow is of a temporary whose scope has not been extended,
159
+
> // therefore this place expression is transient.
160
+
> constC: () = { _=&mut0u8; };
161
+
> ```
162
+
>
163
+
> ```rust
164
+
> // When a temporary is promoted but not lifetime extended, its
165
+
> // place expression is still treated as transient.
0 commit comments