Trait Yokeable
unsafe trait Yokeable<'a>: 'static
The Yokeable<'a> trait is implemented on the 'static version of any zero-copy type; for
example, Cow<'static, T> implements Yokeable<'a> (for all 'a).
One can use
Yokeable::Output on this trait to obtain the "lifetime'd" value of the Cow<'static, T>,
e.g. <Cow<'static, T> as Yokeable<'a>'>::Output is Cow<'a, T>.
A Yokeable type is essentially one with a covariant lifetime parameter,
matched to the parameter in the trait definition. The trait allows one to cast
the covariant lifetime to and from 'static.
Most of the time, if you need to implement Yokeable, you should be able to use the safe
#[derive(Yokeable)] custom derive.
While Rust does not yet have GAT syntax, for the purpose of this documentation
we shall refer to "Self with a lifetime 'a" with the syntax Self<'a>.
Self<'static> is a stand-in for the HKT Self<'_>: lifetime -> type.
With this terminology, Yokeable exposes ways to cast between Self<'static> and Self<'a> generically.
This is useful for turning covariant lifetimes to dynamic lifetimes, where 'static is
used as a way to "erase" the lifetime.
Safety
This trait is safe to implement on types with a covariant lifetime parameter, i.e. one where
[Self::transform()]'s body can simply be { self }. This will occur when the lifetime
parameter is used within references, but not in the arguments of function pointers or in mutable
positions (either in &mut or via interior mutability)
This trait must be implemented on the 'static version of such a type, e.g. one should
implement Yokeable<'a> (for all 'a) on Cow<'static, T>.
This trait is also safe to implement on types that do not borrow memory.
There are further constraints on implementation safety on individual methods.
Implementation example
Implementing this trait manually is unsafe. Where possible, you should use the safe
#[derive(Yokeable)] custom derive instead. We include an example
in case you have your own zero-copy abstractions you wish to make yokeable.
# use Yokeable;
# use Cow;
# use ;
unsafe
Associated Types
type Output: Outlives("'a")This type MUST be
Selfwith the'staticreplaced with'a, i.e.Self<'a>
Required Methods
fn transform(self: &'a Self) -> &'a <Self as >::OutputThis method must cast
selfbetween&'a Self<'static>and&'a Self<'a>.Implementation safety
If the invariants of
Yokeableare being satisfied, the body of this method should simply be{ self }, though it's acceptable to include additional assertions if desired.fn transform_owned(self: Self) -> <Self as >::OutputThis method must cast
selfbetweenSelf<'static>andSelf<'a>.Implementation safety
If the invariants of
Yokeableare being satisfied, the body of this method should simply be{ self }, though it's acceptable to include additional assertions if desired.unsafe fn make(from: <Self as >::Output) -> SelfThis method can be used to cast away
Self<'a>'s lifetime.Safety
The returned value must be destroyed before the data
fromwas borrowing from is.Implementation safety
A safe implementation of this method must be equivalent to a transmute between
Self<'a>andSelf<'static>fn transform_mut<F>(self: &'a mut Self, f: F) where F: 'static + for<'b> FnOnce(&'b mut <Self as >::Output)This method must cast
selfbetween&'a mut Self<'static>and&'a mut Self<'a>, and pass it tof.Implementation safety
A safe implementation of this method must be equivalent to a pointer cast/transmute between
&mut Self<'a>and&mut Self<'static>being passed tofWhy is this safe?
Typically covariant lifetimes become invariant when hidden behind an
&mut, which is why the implementation of this method cannot just bef(self). The reason behind this is that while reading a covariant lifetime that has been cast to a shorter one is always safe (this is roughly the definition of a covariant lifetime), writing may not necessarily be safe since you could write a smaller reference to it. For example, the following code is unsound because it manages to stuff a'alifetime into aCow<'static># use Cow; # use Yokeable;However, this code will not compile because [
Yokeable::transform_mut()] requiresF: 'static. This enforces that whileFmay mutateSelf<'a>, it can only mutate it in a way that does not insert additional references. For example,Fmay callto_owned()on aCowand mutate it, but it cannot insert a new borrowed reference because it has nowhere to borrow from --fdoes not contain any borrowed references, and while we give itSelf<'a>(which contains borrowed data), that borrowed data is known to be validNote that the
for<'b>is also necessary, otherwise the following code would compile:# use Cow; # use Yokeable; # use mem; # // also safely implements Yokeable<'a> # # unsafewhich is unsound because
barcould be moved later, and we do not want to be able to self-insert references to it.The
for<'b>enforces this by stopping the author of the closure from matching up the input&'b Self::Outputlifetime with'aand borrowing directly from it.Thus the only types of mutations allowed are ones that move around already-borrowed data, or introduce new owned data:
# use Cow; # use Yokeable;More formally, a reference to an object that
fassigns to a reference in Self<'a> could be obtained from:- a local variable: the compiler rejects the assignment because 'a certainly outlives local variables in f.
- a field in its argument: because of the for<'b> bound, the call to
fmust be valid for a particular 'b that is strictly shorter than 'a. Thus, the compiler rejects the assignment. - a reference field in Self<'a>: this does not extend the set of non-static lifetimes reachable from Self<'a>, so this is fine.
- one of f's captures: since F: 'static, the resulting reference must refer to 'static data.
- a static or thread_local variable: ditto.
Implementors
impl<'a> Yokeable for isizeimpl<'a, T: 'static> Yokeable for Vec<T>impl<'a, T1: 'static + for<'b> Yokeable<'b>, T2: 'static + for<'b> Yokeable<'b>> Yokeable for (T1, T2)impl<'a> Yokeable for u32impl<'a> Yokeable for i8impl<'a> Yokeable for i128impl<'a, T: 'static + for<'b> Yokeable<'b>> Yokeable for Option<T>impl<'a, T: 'static + ?Sized> Yokeable for &'static Timpl<'a> Yokeable for u16impl<'a> Yokeable for usizeimpl<'a> Yokeable for i64impl<'a> Yokeable for boolimpl<'a, T: 'static + ToOwned + ?Sized> Yokeable for Cow<'static, T>impl<'a> Yokeable for u8impl<'a> Yokeable for u128impl<'a> Yokeable for i32impl<'a> Yokeable for charimpl<'a, T: ?Sized + 'static> Yokeable for PhantomData<T>impl<'a, T: 'static + for<'b> Yokeable<'b>, N: usize> Yokeable for [T; N]impl<'a> Yokeable for ()impl<'a> Yokeable for u64impl<'a> Yokeable for i16