|
1 | 1 | # Disallow references to static mut
|
2 | 2 |
|
3 | 3 | 🚧 The 2024 Edition has not yet been released and hence this section is still "under construction".
|
| 4 | +More information may be found in the tracking issue at <https://github.com/rust-lang/rust/issues/123758>. |
4 | 5 |
|
5 | 6 | ## Summary
|
6 | 7 |
|
7 |
| -- The [`static_mut_refs`] lint is now a hard error that cannot be disabled. |
8 |
| - This prevents taking a shared or mutable reference to a `static mut`. |
| 8 | +- The [`static_mut_refs`] lint level is now `deny` by default. |
| 9 | + This checks for taking a shared or mutable reference to a `static mut`. |
9 | 10 |
|
10 | 11 | [`static_mut_refs`]: ../../rustc/lints/listing/warn-by-default.html#static-mut-refs
|
11 | 12 |
|
12 | 13 | ## Details
|
13 | 14 |
|
14 |
| -Taking a reference to a [`static mut`] is no longer allowed: |
| 15 | +The [`static_mut_refs`] lint detects taking a reference to a [`static mut`]. In the 2024 Edition, this lint is now `deny` by default to emphasize that you should avoid making these references. |
15 | 16 |
|
16 |
| -<!-- edition2024,E0796 --> |
| 17 | +<!-- edition2024 --> |
17 | 18 | ```rust
|
18 | 19 | static mut X: i32 = 23;
|
19 | 20 | static mut Y: i32 = 24;
|
20 | 21 |
|
21 | 22 | unsafe {
|
22 |
| - let y = &X; // ERROR: reference of mutable static |
23 |
| - let ref x = X; // ERROR: reference of mutable static |
24 |
| - let (x, y) = (&X, &Y); // ERROR: reference of mutable static |
| 23 | + let y = &X; // ERROR: shared reference to mutable static |
| 24 | + let ref x = X; // ERROR: shared reference to mutable static |
| 25 | + let (x, y) = (&X, &Y); // ERROR: shared reference to mutable static |
25 | 26 | }
|
26 | 27 | ```
|
27 | 28 |
|
28 | 29 | Merely taking such a reference in violation of Rust's mutability XOR aliasing requirement has always been *instantaneous* [undefined behavior], **even if the reference is never read from or written to**. Furthermore, upholding mutability XOR aliasing for a `static mut` requires *reasoning about your code globally*, which can be particularly difficult in the face of reentrancy and/or multithreading.
|
29 | 30 |
|
| 31 | +Note that there are some cases where implicit references are automatically created without a visible `&` operator. For example, these situations will also trigger the lint: |
| 32 | + |
| 33 | +<!-- edition2024 --> |
| 34 | +```rust |
| 35 | +static mut NUMS: &[u8; 3] = &[0, 1, 2]; |
| 36 | + |
| 37 | +unsafe { |
| 38 | + println!("{NUMS:?}"); // ERROR: shared reference to mutable static |
| 39 | + let n = NUMS.len(); // ERROR: shared reference to mutable static |
| 40 | +} |
| 41 | +``` |
| 42 | + |
30 | 43 | ## Alternatives
|
31 | 44 |
|
32 | 45 | Wherever possible, it is **strongly recommended** to use instead an *immutable* `static` of a type that provides *interior mutability* behind some *locally-reasoned abstraction* (which greatly reduces the complexity of ensuring that Rust's mutability XOR aliasing requirement is upheld).
|
33 | 46 |
|
34 |
| -In situations where no locally-reasoned abstraction is possible and you are therefore compelled still to reason globally about accesses to your `static` variable, you must now use raw pointers such as can be obtained via the [`addr_of_mut!`] macro. By first obtaining a raw pointer rather than directly taking a reference, (the safety requirements of) accesses through that pointer will be more familiar to `unsafe` developers and can be deferred until/limited to smaller regions of code. |
| 47 | +In situations where no locally-reasoned abstraction is possible and you are therefore compelled still to reason globally about accesses to your `static` variable, you must now use raw pointers such as can be obtained via the [`&raw const` or `&raw mut` operators][raw]. By first obtaining a raw pointer rather than directly taking a reference, (the safety requirements of) accesses through that pointer will be more familiar to `unsafe` developers and can be deferred until/limited to smaller regions of code. |
35 | 48 |
|
36 | 49 | [Undefined Behavior]: ../../reference/behavior-considered-undefined.html
|
37 | 50 | [`static mut`]: ../../reference/items/static-items.html#mutable-statics
|
38 | 51 | [`addr_of_mut!`]: https://docs.rust-lang.org/core/ptr/macro.addr_of_mut.html
|
| 52 | +[raw]: ../../reference/expressions/operator-expr.html#raw-borrow-operators |
39 | 53 |
|
40 | 54 | ## Migration
|
41 | 55 |
|
42 |
| -🚧 The automatic migration for this has not yet been implemented. |
43 |
| - |
44 |
| -<!-- TODO: Discuss alternatives around rewriting your code. --> |
| 56 | +There is no automatic migration to fix these references to `static mut`. To avoid undefined behavior you must rewrite your code to use a different approach as recommended in the [Alternatives](#alternatives) section. |
0 commit comments