summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs133
1 files changed, 129 insertions, 4 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 8a4b81e..44a5a50 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,11 +7,131 @@
 
 #![feature(generic_associated_types)]
 #![no_std]
-//! Pain-free self-referential pinned types.
+
+//! Pain-free self-referential/recursively-referential pinned types.
+//!
+//! Because this crate optimizes for recursive references, it's much nicer to
+//! use for porting/copying C code than alternatives. However, the cost is that
+//! it requires generic associated types (GATs). Further, this is the only
+//! crate for self-referential types which supports additional lifetimes than
+//! the self-referential one (with the small ergonomic caveat that closures
+//! don't support where bounds for now, so a proper trait has to be used).
+//!
+//! When using this crate, all you have to do is define your struct like you
+//! would in C, and then tell `selfref` about it. However, do watch out; the
+//! following will not be usable, despite compiling:
+//!
+//! ```rust
+//! #![feature(generic_associated_types)]
+//!
+//! use selfref::opaque;
+//!
+//! // This is the actual self-referential struct.
+//! struct MySelfRefStruct<'this> {
+//!     this: &'this MySelfRefStruct<'this>,
+//! }
+//!
+//! // This is a "marker" type, used to tell `selfref` about the type.
+//! // This is actually the "type family" GAT pattern.
+//! struct MySelfRefStructKey;
+//!
+//! // This tells `selfref` about our type.
+//! opaque! {
+//!     impl Opaque for MySelfRefStructKey {
+//!         type Kind<'this> = MySelfRefStruct<'this>;
+//!     }
+//! }
+//! ```
+//!
+//! That's because there's no way to create the reference
+//! `&'this MySelfRefStruct<'this>` before constructing the struct! That is,
+//! you cannot do this:
+//!
+//! ```rust compile_fail
+//! struct MySelfRefStruct<'this> {
+//!     this: &'this MySelfRefStruct<'this>,
+//! }
+//!
+//! fn main() {
+//!     let x = MySelfRefStruct { this: &x };
+//! }
+//! ```
+//!
+//! But then, you cannot do this in C either. Instead, to make it usable, we
+//! use an `Option` and, to be able to set it, a `Cell`, like so:
+//!
+//! ```rust
+//! #![feature(generic_associated_types)]
+//!
+//! use std::cell::Cell;
+//!
+//! use selfref::opaque;
+//!
+//! struct MySelfRefStruct<'this> {
+//!     this: Cell<Option<&'this MySelfRefStruct<'this>>>,
+//! }
+//!
+//! struct MySelfRefStructKey;
+//!
+//! opaque! {
+//!     impl Opaque for MySelfRefStructKey {
+//!         type Kind<'this> = MySelfRefStruct<'this>;
+//!     }
+//! }
+//! ```
+//!
+//! and then we can use it:
+//!
+//! ```rust
+//! // lines from the above example have been omitted
+//!
+//! # #![feature(generic_associated_types)]
+//! #
+//! # use std::cell::Cell;
+//! #
+//! use selfref::Holder;
+//! use selfref::new_with_closure;
+//! # use selfref::opaque;
+//! use selfref::operate_in_closure;
+//! #
+//! # struct MySelfRefStruct<'this> {
+//! #     this: Cell<Option<&'this MySelfRefStruct<'this>>>,
+//! # }
+//! #
+//! # struct MySelfRefStructKey;
+//! #
+//! # opaque! {
+//! #     impl Opaque for MySelfRefStructKey {
+//! #         type Kind<'this> = MySelfRefStruct<'this>;
+//! #     }
+//! # }
+//!
+//! fn main() {
+//!     // first, construct the struct
+//!     let holder = Box::pin(Holder::<'_, MySelfRefStructKey>::new_with(
+//!         new_with_closure::<MySelfRefStructKey, _>(|_| {
+//!             MySelfRefStruct {
+//!                 this: Cell::new(None)
+//!             }
+//!         })
+//!     ));
+//!
+//!     // then, build the self-reference
+//!     holder.as_ref().operate_in(
+//!         operate_in_closure::<MySelfRefStructKey, _, _>(|this| {
+//!             this.this.set(Some(this.get_ref()));
+//!         })
+//!     );
+//! }
+//! ```
+//!
+//! # Nightly
 //!
 //! This crate (currently) requires nightly, as it relies on GATs.
 //!
-//! # Example
+//! # Examples
+//!
+//! This is a more complex example borrowing from an external lifetime:
 //!
 //! ```rust
 //! #![feature(generic_associated_types)]
@@ -40,6 +160,7 @@
 //! }
 //!
 //! fn main() {
+//!     // can't use real closure, "hand-roll" a closure.
 //!     struct FooBuilder<'b>(&'b str);
 //!     impl<'k, 'b: 'k> NewWith<'k, FooKey<'b>> for FooBuilder<'b> {
 //!         fn new_with<'a>(self) -> Foo<'a, 'b> where 'k: 'a {
@@ -49,11 +170,15 @@
 //!             }
 //!         }
 //!     }
-//!     let stack_array: [u8; 5] = *b"hello";
+//!
 //!     // a non-'static &str
+//!     let stack_array: [u8; 5] = *b"hello";
 //!     let stack_str = core::str::from_utf8(&stack_array).unwrap();
+//!
+//!     // construct the struct
 //!     let holder = pin!(Holder::new_with(FooBuilder(stack_str)));
-//!     // Actually making our Foo refer to itself.
+//!
+//!     // setup the self-reference
 //!     struct SetFooRef;
 //!     impl<'k, 'b: 'k> OperateIn<'k, FooKey<'b>> for SetFooRef {
 //!         type Out = ();