All types with generic parameters have a variance with respect to those parameters.
In Rust lifetimes form a subtype relationship: 'static is a subtype of 'a because it is valid for longer.
Key variance rules:
&'a Tis covariant in both'aandT: you can provide&'static Twhere&'a Tis expected&mut Tis invariant inT: you must provide exactlyT, not a subtype or supertype- function arguments are contravariant — a function that accepts a longer-lived reference can be used where a shorter-lived one is expected
See also
- Variance Describes When a Subtype Can Be Used in Place of a Supertype, Covariant, Invariant, or Contravariant — the general concept this note applies to Rust lifetimes specifically
- A Lifetime Names the Region of Code a Reference Must Be Valid For, Not Necessarily the Full Scope — the subtype relationship between lifetimes is grounded in the definition: a longer lifetime is a subtype because it satisfies every constraint a shorter one would
- ‘static Means Valid Until Program Shutdown — Static Variables Have It, But Not All ‘static References Point to Static Memory —
'staticis the bottom of the lifetime subtype hierarchy: it is a subtype of every lifetime, which is why&'static Tcan be used wherever&'a Tis expected - &mut T Is an Exclusive Reference, No Other Reference Can Coexist With It —
&mut Tbeing invariant inTis a direct consequence of its exclusivity guarantee; covariance would allow type-unsafe writes through the exclusive reference - Reliability means preventing faults from causing failures — invariance of
&mut Tis a compile-time reliability mechanism: the unsoundness it prevents (writing the wrong type through an exclusive reference) would be a fault that propagates silently into a failure
References
- J. Gjengset, Rust for Rustaceans: Idiomatic Programming for Experienced Developers. No Starch Press, 2021.