Skip to main content

Variance

Enum Variance 

Source
#[repr(u8)]
pub enum Variance { Bivariant = 0, Covariant = 1, Contravariant = 2, Invariant = 3, }
Expand description

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) == X for any variance X

When flipped (for contravariant positions like fn arguments):

  • Bivariant.flip() == Bivariant (no change)

See GitHub Issue #1708

§

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.

See Rust Reference: Covariance

§

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

See Rust Reference: Contravariance

§

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) == Invariant for any variance X

See Rust Reference: Invariance

Implementations§

Source§

impl Variance

Source

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.

See GitHub Issue #1708

Source

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.

See Rust Reference: Variance of built-in types

Source

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).

See Rust Reference: Variance of built-in types

Source

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.

See Rust Reference: Variance of built-in types

Source

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
Source

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
Source

pub const fn can_shrink(self) -> bool

Returns true if lifetimes can be safely shrunk ('static'a).

True for Covariant and Bivariant types.

Source

pub const fn can_grow(self) -> bool

Returns true if lifetimes can be safely grown ('a'static).

True for Contravariant and Bivariant types.

Trait Implementations§

Source§

impl Clone for Variance

Source§

fn clone(&self) -> Variance

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Variance

Source§

impl Debug for Variance

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Variance

Source§

fn default() -> Variance

Returns the “default value” for a type. Read more
Source§

impl Eq for Variance

Source§

impl Hash for Variance

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Variance

Source§

fn eq(&self, other: &Variance) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Variance

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.