A type T
is 'static
if any value of that type is guaranteed no to have any dangling references or borrows even if it were to exist / be owned until the end of time.
- This definition may look contrived, but is exactly what is required for soundness: if you want to run a closure in another thread, which may run it arbitrarily late, Rust will require that the closure be guaranteed not to use any dangling pointers (that would be unsound). A way of guaranteeing it is by guaranteeing the stronger property of not even posessing such dangling pointers, and a way of guaranteeing that a particular instance does not posess such dangling pointer is by guaranteeing that all the elements / instances of that type cannot posess such dangling pointer.
As a practical rule of thumb, you can ask yourself the question: could I store a value of that type in a static
/ global variable?
For instance, a String
, in practice, almost always ends up dropped before the end of the program, so you may be tempted to think that a String
cannot be 'static
. Which is false: imagine the following program:
use ::spin::{ // 0.5.2
Mutex,
};
static GLOBAL_VARIABLE: Mutex<Option<String>> = Mutex::new(None);
fn main ()
{
let s = String::from("Hello, World!");
*GLOBAL_VARIABLE.lock() = Some(s);
// Now `s` lives in / is held by a global variable,
// until the end of the program life.
}
So, long story short, all the "primitive" types are 'static
.
There are only two counter examples to this:
-
Rust references (
&'a T
or&'a mut T
), whichmaydangle after the lifetime of the borrow ('a
)- Only a
&'static T
/&'static mut T
gets to be'static
(and requires thatT : 'static
)
- Only a
-
any
struct
orenum
/ newtype containing a Rust reference gets "infected" with the'a
lifetime parameter and bound.
Example
use ::spin::{ // 0.5.2
Mutex,
};
static GLOBAL_VARIABLE: Mutex<Option<&str>> = Mutex::new(None);
fn main ()
{
let s = String::from("Hello, World!");
*GLOBAL_VARIABLE.lock() = Some(&s);
// Error, `&s` dangles at some point,
// so it cannot be stored in a forever-living global variable
}
-
error[E0597]: `s` does not live long enough --> src/main.rs:10:36 | 10 | *GLOBAL_VARIABLE.lock() = Some(&s); | ---------------------- ^^ borrowed value does not live long enough | | | argument requires that `s` is borrowed for `'static` ... 13 | } | - `s` dropped here while still borrowed
Rule of thumb
-
Any non-generic type is automatically
'static
-
Any generic type is
'static
only when instanced with'static
lifetimes (for the generic lifetime parameters) and types that recursively are'static
(for the generic type parameters).- For instance, the type
Ref<'a, T>
only gets to be/// Two generic parameters: /// /// - a lifetime parameter `'a`, /// /// - and a type parameter `T`. struct Ref<'a, T> { field: &'a T, }
'static
ifT : 'static
(e.g.,T = String
) and'a = 'static
- For instance, the type