x-selfref
This basically a copy/fork of the MIT-licensed selfref library (by another author), with a few additions made by me.
Introduction of selfref
An experimental approach to self-referential structs in Rust.
This crate provides an alternative approach to self-referential structs, where instead of providing you with a macro or framework where you define a self-referential struct and it handles all of the details for you, we try to expose the abstractions and building blocks for making self-referential structs work well in safe Rust.
For example, a [Holder
] is a safe wrapper around a self-referential
struct, providing safe APIs for constructing and manipulating a
self-referential struct. However, and unlike other self-referential crates,
it does not dictate the backing storage of the struct. The [Opaque
] trait
is used to identify a self-referential struct for use with a [Holder
] -
since Rust does not support higher kinded types (HKTs), this crate uses
generic associated types (GATs) as a workaround.
To use the crate, first define a self-referential struct in plain Rust:
use Cell;
// Your self-referential struct.
Then, define a type to implement the Opaque
. This can be done
automatically with the opaque
macro:
# use Cell;
# // Your self-referential struct.
#
use opaque;
// A "marker type" that implements `Opaque`.
// This follows the "type family" GAT pattern.
;
opaque!
// Alternatively, it is possible to implement `Opaque` on, for example,
// `MySelfRefStruct<'static>`, but the added lifetime adds verbosity which
// may be considered unnecessary/undesired.
Now you can construct a Holder
and pick a storage for it. For example,
in a Box
:
# use Cell;
# // Your self-referential struct.
#
# use opaque;
# // A "marker type" that implements `Opaque`.
# // This follows the "type family" GAT pattern.
# ;
# opaque!
# // Alternatively, it is possible to implement `Opaque` on, for example,
# // `MySelfRefStruct<'static>`, but the added lifetime adds verbosity which
# // may be considered unnecessary/undesired.
use Holder;
Examples
This is a more complex example borrowing from an external lifetime:
use Cell;
use PhantomData;
use Pin;
use Holder;
use opaque;
;
opaque!
Features
Due to PhantomData is unsound
we currently require the following features for T: ?Sized
support in
xselfref::opaque!
:
alloc
-xselfref::opaque!
forT: ?Sized
is provided byBox
.nightly
-xselfref::opaque!
forT: ?Sized
is provided by a wrapper aroundPhantomData
, which works around the above issue. we call this "PhantomDrop".
When enabling both features, nightly
takes over and we use the wrapper
always. This doesn't make a significant difference since the generated UB
check is dead code anyway, but PhantomDrop
doesn't depend on alloc
and
can be used in no_std
environments.
If not using either feature, T: ?Sized
support requires unsafe
ly
implementing Opaque
.
Note that we do not enable any features by default! We assume most
folks aren't coming to this crate for its T: ?Sized
support, so these are
the best defaults for crates to depend on. If they do need the ?Sized
support they can just enable one of these (probably alloc
).