rec_cell 0.1.0

Zero-cost borrow-checking of aliased references with cyclic construction
Documentation
//! Compile-fail examples. Partially adapted from GhostCell and qcell's `LCell`
//! tests.
//!
//! A token cannot escape its scope:
//!
//! ```compile_fail
//! use rec_cell::RecToken;
//! let _: RecToken<'static> = RecToken::new(|token| token);
//! ```
//!
//! A branded cell cannot escape with its token:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! let _ = RecToken::new(|mut token| {
//!     let cell = RecCell::new(42);
//!     *cell.borrow_mut(&mut token) = 33;
//!     cell
//! });
//! ```
//!
//! A shared borrow keeps the token alive:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|token| {
//!     let cell = RecCell::new(42);
//!     let value = cell.borrow(&token);
//!     drop(token);
//!     let _ = *value;
//! });
//! ```
//!
//! A mutable token borrow excludes every other token-gated borrow, including a
//! borrow of another cell:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|mut token| {
//!     let one = RecCell::new(1);
//!     let two = RecCell::new(2);
//!     let one = one.borrow_mut(&mut token);
//!     assert_eq!(*two.borrow(&token), 2);
//!     *one = 3;
//! });
//! ```
//!
//! A cell cannot be dropped while it is borrowed:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|token| {
//!     let cell = RecCell::new(42);
//!     let value = cell.borrow(&token);
//!     drop(cell);
//!     let _ = *value;
//! });
//! ```
//!
//! The cell itself remains borrowed while its token-gated reference exists:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|mut token| {
//!     let mut cell = RecCell::new(42);
//!     let value = cell.borrow(&token);
//!     *cell.get_mut() = 0;
//!     let _ = *value;
//! });
//! ```
//!
//! Conversely, `get_mut` excludes token-gated access:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|token| {
//!     let mut cell = RecCell::new(42);
//!     let value = cell.get_mut();
//!     assert_eq!(*cell.borrow(&token), 42);
//!     *value = 0;
//! });
//! ```
//!
//! Distinct token brands cannot access each other's cells:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|token1| {
//!     let cell = RecCell::new(42);
//!     RecToken::new(|token2| {
//!         let _ = cell.borrow(&token1);
//!         let _ = cell.borrow(&token2);
//!     });
//! });
//! ```
//!
//! A cursor retains its mutable token borrow:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|mut token| {
//!     let one = RecCell::new(1);
//!     let two = RecCell::new(2);
//!     let cursor = one.cursor_mut(&mut token);
//!     assert_eq!(*two.borrow(&token), 2);
//!     drop(cursor);
//! });
//! ```
//!
//! A shared cursor likewise retains its shared token borrow, so an exclusive
//! token borrow cannot be created while the cursor exists:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|mut token| {
//!     let cell = RecCell::new(1);
//!     let cursor = cell.cursor(&token);
//!     *cell.borrow_mut(&mut token) = 2;
//!     assert_eq!(cursor.get(), &2);
//! });
//! ```
//!
//! Token-gated references also keep the cell borrowed, excluding direct
//! mutable access through `get_mut`:
//!
//! ```compile_fail
//! use rec_cell::{RecCell, RecToken};
//! RecToken::new(|mut token| {
//!     let mut cell = RecCell::new(1);
//!     let cursor = cell.cursor_mut(&mut token);
//!     *cell.get_mut() = 2;
//!     drop(cursor);
//! });
//! ```
//!
//! A cyclic constructor's borrow keeps its storage in place. Dropping the
//! token does not make it valid to move that storage while the resulting
//! self-reference may exist:
//!
//! ```compile_fail
//! use core::mem::MaybeUninit;
//! use rec_cell::{RecCell, RecToken};
//!
//! struct Node<'a, 't> { next: &'a RecCell<'t, Node<'a, 't>> }
//!
//! RecToken::new(|token| {
//!     let mut slot = MaybeUninit::<Node<'_, '_>>::uninit();
//!     let ((), token) = RecCell::new_cyclic(&mut slot, token, |cell| {
//!         ((), Node { next: cell })
//!     });
//!     drop(token);
//!     let _moved = slot;
//! });
//! ```
//!
//! A builder cannot be completed without returning its linear capability:
//!
//! ```compile_fail
//! use rec_cell::RecToken;
//! RecToken::new(|token| {
//!     let _ = token.with_builder(|_| Ok::<_, ()>(((), ())));
//! });
//! ```
//!
//! Only safe-to-share values produce `Sync` cells, and only sendable values
//! produce `Send` cells:
//!
//! ```compile_fail
//! use std::rc::Rc;
//! use rec_cell::RecCell;
//! fn assert_send<T: Send>() {}
//! assert_send::<RecCell<'static, Rc<()>>>();
//! ```
//!
//! ```compile_fail
//! use core::cell::Cell;
//! use rec_cell::RecCell;
//! fn assert_sync<T: Sync>() {}
//! assert_sync::<RecCell<'static, Cell<()>>>();
//! ```