pub static CONST_ITEM_MUTATION: &Lint
Expand description
The const_item_mutation
lint detects attempts to mutate a const
item.
§Example
const FOO: [i32; 1] = [0];
fn main() {
FOO[0] = 1;
// This will print "[0]".
println!("{:?}", FOO);
}
{{produces}}
§Explanation
Trying to directly mutate a const
item is almost always a mistake.
What is happening in the example above is that a temporary copy of the
const
is mutated, but the original const
is not. Each time you
refer to the const
by name (such as FOO
in the example above), a
separate copy of the value is inlined at that location.
This lint checks for writing directly to a field (FOO.field = some_value
) or array entry (FOO[0] = val
), or taking a mutable
reference to the const item (&mut FOO
), including through an
autoderef (FOO.some_mut_self_method()
).
There are various alternatives depending on what you are trying to accomplish:
- First, always reconsider using mutable globals, as they can be difficult to use correctly, and can make the code more difficult to use or understand.
- If you are trying to perform a one-time initialization of a global:
- If the value can be computed at compile-time, consider using const-compatible values (see Constant Evaluation).
- For more complex single-initialization cases, consider using
std::sync::LazyLock
.
- If you truly need a mutable global, consider using a
static
, which has a variety of options:- Simple data types can be directly defined and mutated with an
atomic
type. - More complex types can be placed in a synchronization primitive
like a
Mutex
, which can be initialized with one of the options listed above. - A mutable
static
is a low-level primitive, requiring unsafe. Typically This should be avoided in preference of something higher-level like one of the above.
- Simple data types can be directly defined and mutated with an