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
As it turns out, the story that "the final value of a constant cannot
contain any mutable references" has some nuance to it. Let's describe
these caveats.
Thanks to theemathas for noticing these and to RalfJ for filling in
context.
The final value of a `const` itemcannot contain any mutable references.
52
+
The final value of a `const` item, after the initializer is evaluated to a value that has the declared type of the constant, cannot contain any mutable references except as described below.
53
53
54
54
```rust
55
55
# #![allow(static_mut_refs)]
56
56
staticmutS:u8=0;
57
-
constC:&u8=unsafe { &mutS }; // OK
57
+
const_:&u8=unsafe { &mutS }; // OK.
58
+
// ^^^^^^
59
+
// Allowed since this is coerced to `&S`.
58
60
```
59
61
60
62
```rust
61
63
# usecore::sync::atomic::AtomicU8;
62
64
staticS:AtomicU8=AtomicU8::new(0);
63
-
constC:&AtomicU8=&S; // OK
65
+
const_:&AtomicU8=&S; // OK.
66
+
// ^^
67
+
// Allowed even though the shared reference is to an interior
68
+
// mutable value.
64
69
```
65
70
66
71
```rust,compile_fail,E0080
67
72
# #![allow(static_mut_refs)]
68
73
static mut S: u8 = 0;
69
-
const C: &mut u8 = unsafe { &mut S }; // ERROR not allowed
74
+
const _: &mut u8 = unsafe { &mut S }; // ERROR.
75
+
// ^^^^^^
76
+
// Not allowed as the mutable reference appears in the final value.
// Not allowed as the mutable reference appears in the final value,
85
+
// even though type erasure occurs.
86
+
```
87
+
88
+
Mutable references where the referent is a value of a [zero-sized type] are allowed.
89
+
90
+
```rust
91
+
# #![allow(static_mut_refs)]
92
+
staticmutS: () = ();
93
+
const_:&mut () =unsafe { &mutS }; // OK.
94
+
// ^^ This is a zero-sized type.
95
+
```
96
+
97
+
```rust
98
+
# #![allow(static_mut_refs)]
99
+
staticmutS: [u8; 0] = [0; 0];
100
+
const_:&mut [u8; 0] =unsafe { &mutS }; // OK.
101
+
// ^^^^^^^ This is a zero-sized type.
102
+
```
103
+
104
+
> [!NOTE]
105
+
> This is allowed as, for a value of a zero-sized type, no bytes can actually be mutated. We must accept this as `&mut []` is [promoted].
106
+
107
+
Values of [union type] are not considered to contain any references; for this purpose, a value of union type is treated as a sequence of untyped bytes.
108
+
109
+
```rust
110
+
# #![allow(static_mut_refs)]
111
+
unionU { f:&'staticmutu8 }
112
+
staticmutS:u8=0;
113
+
const_:U=unsafe { U { f:&mutS }}; // OK.
114
+
// ^^^^^^^^^^^^^^^
115
+
// This is treated as a sequence of untyped bytes.
116
+
```
117
+
118
+
Mutable references contained within a [mutable static] may be referenced in the final value of a constant.
> Here, the `AtomicU8` is a temporary that is lifetime extended to `'static` (see [destructors.scope.lifetime-extension.static]), and references to lifetime-extended temporaries with interior mutability are not allowed in the final value of a constant expression (see [const-eval.const-expr.borrows]).
0 commit comments