Trait transient::Transience

source ·
pub trait Transience: Sized + CanTranscendTo<Self> + CanRecoverFrom<Self> { }
Expand description

Marker trait for types used to establish the variance of a type with respect to each of its lifetime parameters, including Co, Contra, Inv, Timeless, and tuples combining them.

Note that even though most types are covariant in reality, this crate treats invariance as the default since any other assumption could cause undefined behavior if chosen incorrectly. To override this default, the Transience associated type can be set in the type’s Transient implementation; if using the derive macro, this corresponds to including the #[r#unsafe(covariant)] attribute.

To maximize the flexibility of this crate’s functionality, transitions between compatible Transiences are supported. See the documentation for the CanTranscendTo and CanRecoverFrom traits for an introduction to these transitions and when they are used, as well as a discussion of why certain transitions are allowed while others are forbidden.

§Valid transitions table

The following table summarizes the allowable transitions that can be made between (single-lifetime) transiences, where the rows represent the starting point for a type (i.e. the Transience it defines in its Transient impl), and the columns represent a transience it wishes to transition to (i.e. when being cast to dyn Any<_>). Upon being downcast the trait object would then return to a row in the table, ideally back where it started (although not always, as discussed in the next section):

Inv<'short> Inv<'long> Co<'short> Co<'long> Contra<'short> Contra<'long> Timeless
Inv<'short> yes no no no no no no
Inv<'long> no yes no no no no no
Co<'short> yes no yes no no no no
Co<'long> yes yes yes yes no no no
Contra<'short> yes yes no no yes yes no
Contra<'long> no yes no no no yes no
Timeless yes yes yes yes yes yes yes

§Lossy transitions

The yellow transitions marked with an asterisk in the above table are allowed, but lossy; the recovered lifetime will be reduced (Co) or increased (Contra). For example, a type &'long i32 with a transience of Co<'long> (middle row) can be safely erased to the trait object dyn Any<Co<'short>> (3rd column) by shortening its lifetime. However, when we want to downcast the opaque trait object back into its concrete type, we cannot just assume (at least under the implementation of this crate) that we can safely recover a 'long lifetime from the 'short lifetime of the trait object; instead, we can only safely recover &'short i32 from the dyn Any<Co<'short>>. As a result, even though the underlying reference should actually be valid for the 'long lifetime, we end up with a reference that the borrow-checker only believes to be valid for the 'short lifetime. This may seem silly if you happen to be dealing with a case where you know what you are working with and that the 'long lifetime is valid; but the whole point of type-erasure is that sometimes you dont know/care, or you don’t want to compiler to know/care, and sometimes ignorance has a cost. On the bright side, if you really are confident that 'long is valid, you can unsafe-ly fix it using hacks like std::mem::transmute and raw pointer casts (at your own risk, of course).

Object Safety§

This trait is not object safe.

Implementations on Foreign Types§

source§

impl<A1> Transience for (A1,)
where A1: Transience,

source§

impl<A1, B1> Transience for (A1, B1)
where A1: Transience, B1: Transience,

source§

impl<A1, B1, C1> Transience for (A1, B1, C1)
where A1: Transience, B1: Transience, C1: Transience,

source§

impl<A1, B1, C1, D1> Transience for (A1, B1, C1, D1)
where A1: Transience, B1: Transience, C1: Transience, D1: Transience,

Implementors§

source§

impl Transience for Timeless

source§

impl<'a> Transience for Co<'a>

source§

impl<'a> Transience for Contra<'a>

source§

impl<'a> Transience for Inv<'a>