blob: 3b24ceb3b1af8b2c9e5e6f80276ab3170dfb9f6f [file] [log] [blame] [view]
r[items.static]
# Static items
r[items.static.syntax]
```grammar,items
StaticItem ->
ItemSafety?[^extern-safety] `static` `mut`? IDENTIFIER `:` Type ( `=` Expression )? `;`
```
[^extern-safety]: The `safe` and `unsafe` function qualifiers are only allowed semantically within `extern` blocks.
r[items.static.intro]
A *static item* is similar to a [constant], except that it represents an allocation in the
program that is initialized with the initializer expression. All references and raw pointers to the
static refer to the same allocation.
r[items.static.lifetime]
Static items have the `static` lifetime, which outlives all other lifetimes in a Rust program.
Static items do not call [`drop`] at the end of the program.
r[items.static.storage-disjointness]
If the `static` has a size of at least 1 byte, this allocation is disjoint from all other such
`static` allocations as well as heap allocations and stack-allocated variables. However, the storage of
immutable `static` items can overlap with allocations that do not themselves have a unique address, such
as [promoteds] and [`const` items][constant].
r[items.static.namespace]
The static declaration defines a static value in the [value namespace] of the module or block where it is located.
r[items.static.init]
The static initializer is a [constant expression] evaluated at compile time.
Static initializers may refer to and read from other statics.
When reading from mutable statics, they read the initial value of that static.
r[items.static.read-only]
Non-`mut` static items that contain a type that is not [interior mutable] may
be placed in read-only memory.
r[items.static.safety]
All access to a static is safe, but there are a number of restrictions on
statics:
r[items.static.sync]
* The type must have the [`Sync`](std::marker::Sync) trait bound to allow thread-safe access.
r[items.static.init.omission]
The initializer expression must be omitted in an [external block], and must be
provided for free static items.
r[items.static.safety-qualifiers]
The `safe` and `unsafe` qualifiers are semantically only allowed when used in an [external block].
r[items.static.generics]
## Statics & generics
A static item defined in a generic scope (for example in a blanket or default
implementation) will result in exactly one static item being defined, as if
the static definition was pulled out of the current scope into the module.
There will *not* be one item per monomorphization.
This code:
```rust
use std::sync::atomic::{AtomicUsize, Ordering};
trait Tr {
fn default_impl() {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
println!("default_impl: counter was {}", COUNTER.fetch_add(1, Ordering::Relaxed));
}
fn blanket_impl();
}
struct Ty1 {}
struct Ty2 {}
impl<T> Tr for T {
fn blanket_impl() {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
println!("blanket_impl: counter was {}", COUNTER.fetch_add(1, Ordering::Relaxed));
}
}
fn main() {
<Ty1 as Tr>::default_impl();
<Ty2 as Tr>::default_impl();
<Ty1 as Tr>::blanket_impl();
<Ty2 as Tr>::blanket_impl();
}
```
prints
```text
default_impl: counter was 0
default_impl: counter was 1
blanket_impl: counter was 0
blanket_impl: counter was 1
```
r[items.static.mut]
## Mutable statics
r[items.static.mut.intro]
If a static item is declared with the `mut` keyword, then it is allowed to be
modified by the program. One of Rust's goals is to make concurrency bugs hard
to run into, and this is obviously a very large source of race conditions or
other bugs.
r[items.static.mut.safety]
For this reason, an `unsafe` block is required when either reading
or writing a mutable static variable. Care should be taken to ensure that
modifications to a mutable static are safe with respect to other threads
running in the same process.
r[items.static.mut.extern]
Mutable statics are still very useful, however. They can be used with C
libraries and can also be bound from C libraries in an `extern` block.
```rust
# fn atomic_add(_: *mut u32, _: u32) -> u32 { 2 }
static mut LEVELS: u32 = 0;
// This violates the idea of no shared state, and this doesn't internally
// protect against races, so this function is `unsafe`
unsafe fn bump_levels_unsafe() -> u32 {
unsafe {
let ret = LEVELS;
LEVELS += 1;
return ret;
}
}
// As an alternative to `bump_levels_unsafe`, this function is safe, assuming
// that we have an atomic_add function which returns the old value. This
// function is safe only if no other code accesses the static in a non-atomic
// fashion. If such accesses are possible (such as in `bump_levels_unsafe`),
// then this would need to be `unsafe` to indicate to the caller that they
// must still guard against concurrent access.
fn bump_levels_safe() -> u32 {
unsafe {
return atomic_add(&raw mut LEVELS, 1);
}
}
```
r[items.static.mut.sync]
Mutable statics have the same restrictions as normal statics, except that the
type does not have to implement the `Sync` trait.
r[items.static.alternate]
## Using Statics or Consts
It can be confusing whether or not you should use a constant item or a static
item. Constants should, in general, be preferred over statics unless one of the
following are true:
* Large amounts of data are being stored.
* The single-address property of statics is required.
* Interior mutability is required.
[constant]: constant-items.md
[`drop`]: ../destructors.md
[constant expression]: ../const_eval.md#constant-expressions
[external block]: external-blocks.md
[interior mutable]: ../interior-mutability.md
[value namespace]: ../names/namespaces.md
[promoteds]: ../destructors.md#constant-promotion