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