#[repr(u8)]pub enum Variance {
Bivariant = 0,
Covariant = 1,
Contravariant = 2,
Invariant = 3,
}Expand description
Variance of a type with respect to its type/lifetime parameters.
See:
Variants§
Bivariant = 0
Type is bivariant: no lifetime constraints at all.
A type is bivariant if it has no lifetime parameters and contains no references or interior mutability. Such types can be freely substituted regardless of lifetime constraints.
Examples: i32, String, bool, all primitives, types with no lifetime dependency
Bivariant is the “top” of the variance lattice - it imposes no constraints. When combined with any other variance, the other variance “wins”:
Bivariant.combine(X) == Xfor any variance X
When flipped (for contravariant positions like fn arguments):
Bivariant.flip() == Bivariant(no change)
Covariant = 1
Type is covariant: can safely shrink lifetimes ('static → 'a).
A type F<T> is covariant if F<Sub> is a subtype of F<Super> when Sub is a
subtype of Super. This means the type “preserves” the subtyping relationship.
Examples: &'a T, *const T, Box<T>, Vec<T>, [T; N]
Note: Prior to issue #1708, types with no lifetime parameters were also marked as Covariant. Now they should be marked as Bivariant.
Contravariant = 2
Type is contravariant: can safely grow lifetimes ('a → 'static).
A type F<T> is contravariant if F<Super> is a subtype of F<Sub> when Sub is a
subtype of Super. This means the type “reverses” the subtyping relationship.
Examples: fn(T) is contravariant with respect to T
Invariant = 3
Type is invariant: no lifetime or type parameter changes allowed.
A type F<T> is invariant if neither F<Sub> nor F<Super> is a subtype of the other,
regardless of the relationship between Sub and Super.
Examples (overall lifetime variance): *mut T, &'a mut &'b T
Note: &'a mut T is invariant with respect to T, but if T contributes Bivariant
(no lifetime constraints), the overall lifetime variance is still Covariant (from 'a).
Invariant is the “bottom” of the variance lattice - it imposes maximum constraints. When combined with any other variance, Invariant always “wins”:
X.combine(Invariant) == Invariantfor any variance X
Implementations§
Source§impl Variance
impl Variance
Sourcepub const BIVARIANT: fn(&'static Shape) -> Variance = bivariant
pub const BIVARIANT: fn(&'static Shape) -> Variance = bivariant
Function that returns Variance::Bivariant.
Use this for types with no lifetime parameters (like i32, String),
since they impose no constraints on lifetimes.
Bivariant is the “top” of the variance lattice - when combined with any other variance, the other variance wins. When flipped, bivariant stays bivariant.
Sourcepub const COVARIANT: fn(&'static Shape) -> Variance = covariant
pub const COVARIANT: fn(&'static Shape) -> Variance = covariant
Function that returns Variance::Covariant.
Use this for types that are covariant with respect to their type/lifetime parameter,
such as &'a T, *const T, Box<T>, Vec<T>, [T; N].
Note: For types with no lifetime parameters (like i32, String),
use Self::BIVARIANT instead, as they impose no constraints on lifetimes.
Sourcepub const CONTRAVARIANT: fn(&'static Shape) -> Variance = contravariant
pub const CONTRAVARIANT: fn(&'static Shape) -> Variance = contravariant
Function that returns Variance::Contravariant.
Use this for types that are contravariant with respect to their type/lifetime parameter,
such as fn(T) (contravariant with respect to T).
Sourcepub const INVARIANT: fn(&'static Shape) -> Variance = invariant
pub const INVARIANT: fn(&'static Shape) -> Variance = invariant
Function that returns Variance::Invariant.
Use this for types that are invariant with respect to their type/lifetime parameter,
such as *mut T, Cell<T>, UnsafeCell<T>.
This is the safe default when variance is unknown.
Sourcepub const fn combine(self, other: Variance) -> Variance
pub const fn combine(self, other: Variance) -> Variance
Combine two variances (used when a type contains multiple lifetime-carrying fields).
This is the “meet” (greatest lower bound) operation in the variance lattice:
Bivariant (top)
/ \
Covariant Contravariant
\ /
Invariant (bottom)Rules:
- Bivariant is identity:
Bi.combine(X) == X - Same variance: keep it
- Mixed covariant/contravariant: becomes invariant
- Invariant dominates everything
Sourcepub const fn flip(self) -> Variance
pub const fn flip(self) -> Variance
Flip variance (used when type appears in contravariant position, like fn args).
- Bivariant stays Bivariant (no lifetime constraints to flip)
- Covariant ↔ Contravariant
- Invariant stays Invariant
Sourcepub const fn can_shrink(self) -> bool
pub const fn can_shrink(self) -> bool
Returns true if lifetimes can be safely shrunk ('static → 'a).
True for Covariant and Bivariant types.