Expand description
Create a trusted carrier with a new lifetime that is guaranteed to be
unique among other trusted carriers. When you call make_guard!
to make a
unique lifetime, the macro creates a Guard
to hold it. This guard can be
converted into
an Id
, which can be stored in structures to uniquely
“brand” them. A different invocation of the macro will produce a new
lifetime that cannot be unified. The only way to construct these types is
with make_guard!
or unsafe
code.
use generativity::{Id, make_guard};
struct Struct<'id>(Id<'id>);
make_guard!(a);
Struct(a.into());
This is the concept of “generative” lifetime brands. Guard
and Id
are
invariant over
their lifetime parameter, meaning that it is never valid to substitute or
otherwise coerce Id<'a>
into Id<'b>
, for any concrete 'a
or 'b
,
including the 'static
lifetime.
Any invariant lifetime can be “trusted” to carry a brand, so long as they
are known to be restricted to carrying a brand, and haven’t been derived
from some untrusted lifetime (or are completely unbound). When using this
library, it is recommended to always use Id<'id>
to carry the brand, as
this reduces the risk of accidentally trusting an untrusted lifetime.
Importantly, non-invariant lifetimes cannot be trusted, as the variance
allows lifetimes to be contracted to match and copy the brand lifetime.
To achieve lifetime invariance without Id
, there are two standard ways:
PhantomData<&'a mut &'a ()>
and PhantomData<fn(&'a ()) -> &'a ()>
. The
former works because &mut T
is invariant over T
, and the latter works
because fn(T)
is contravariant over T
and fn() -> T
is covariant
over T
, which combines to invariance. Both are equivalent in this case
with T = ()
, but fn(T) -> T
is generally preferred if the only purpose
is to indicate invariance, as function pointers are a perfect cover for all
auto traits (e.g. Send
, Sync
, Unpin
, UnwindSafe
, etc.) and thus
only indicates invariance, whereas &mut T
can carry further implication
of “by example” use of PhantomData
.
Macros§
- make_
guard - Create a
Guard
with a unique invariant lifetime (with respect to other trusted/invariant lifetime brands).