blob: 7b62d0918d59607531471833455763c6310ca973 [file] [log] [blame] [view] [edit]
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 allocated object in the
program that is initialized with the initializer expression. All references and raw pointers to the
static refer to the same allocated object.
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 allocated object is disjoint from all other such
`static` objects as well as heap allocations and stack-allocated variables. However, the storage of
immutable `static` items can overlap with objects 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