self_cell-1.2.1/.cargo_vcs_info.json0000644000000001360000000000100127650ustar { "git": { "sha1": "7b98b472a3948bc5f678b9fdea4a80935368611b" }, "path_in_vcs": "" }self_cell-1.2.1/Cargo.lock0000644000000011170000000000100107400ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "once_cell" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0" [[package]] name = "rustversion" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "self_cell" version = "1.2.1" dependencies = [ "once_cell", "rustversion", ] self_cell-1.2.1/Cargo.toml0000644000000025300000000000100107630ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "self_cell" version = "1.2.1" authors = ["Lukas Bergdoll "] build = false include = [ "src/*.rs", "Cargo.toml", "README.md", "LICENSE", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Safe-to-use proc-macro-free self-referential structs in stable Rust." documentation = "https://docs.rs/self_cell" readme = "README.md" keywords = [ "lifetime", "borrowing", "self", "reference", "intrusive", ] categories = [ "rust-patterns", "memory-management", ] license = "Apache-2.0 OR GPL-2.0-only" repository = "https://github.com/Voultapher/self_cell" [features] old_rust = ["rustversion"] [lib] name = "self_cell" path = "src/lib.rs" [dependencies.rustversion] version = ">=1" optional = true [dev-dependencies.once_cell] version = "=1.1.0" self_cell-1.2.1/Cargo.toml.orig000064400000000000000000000016701046102023000144500ustar 00000000000000[package] name = "self_cell" version = "1.2.1" authors = ["Lukas Bergdoll "] edition = "2018" license = "Apache-2.0 OR GPL-2.0-only" description = "Safe-to-use proc-macro-free self-referential structs in stable Rust." readme = "README.md" documentation = "https://docs.rs/self_cell" repository = "https://github.com/Voultapher/self_cell" keywords = ["lifetime", "borrowing", "self", "reference", "intrusive"] categories = ["rust-patterns", "memory-management"] include = ["src/*.rs", "Cargo.toml", "README.md", "LICENSE"] [dependencies] rustversion = { version = ">=1", optional = true } [dev-dependencies] once_cell = "=1.1.0" [features] # This optional feature lowers the minimum rustc version from 1.51 to 1.36. # However this requires polyfilling std library functionality for older rustc # with technically UB versions. Testing does not show older rustc versions # (ab)using this. Use at old_rust = ["rustversion"] self_cell-1.2.1/README.md000064400000000000000000000170411046102023000130370ustar 00000000000000[github](https://github.com/Voultapher/self_cell) [crates.io](https://crates.io/crates/self_cell) [docs.rs](https://docs.rs/self_cell) # `self_cell!` Use the macro-rules macro: `self_cell!` to create safe-to-use self-referential structs in stable Rust, without leaking the struct internal lifetime. In a nutshell, the API looks *roughly* like this: ```rust // User code: self_cell!( struct NewStructName { owner: Owner, #[covariant] dependent: Dependent, } impl {Debug} ); // Generated by macro: struct NewStructName(...); impl NewStructName { fn new( owner: Owner, dependent_builder: impl for<'a> FnOnce(&'a Owner) -> Dependent<'a> ) -> NewStructName { ... } fn borrow_owner<'a>(&'a self) -> &'a Owner { ... } fn borrow_dependent<'a>(&'a self) -> &'a Dependent<'a> { ... } [...] // See the macro level documentation for a list of all generated functions // and other possible options, e.g. async builder support, // https://docs.rs/self_cell/latest/self_cell/macro.self_cell.html#generated-api. } impl Debug for NewStructName { ... } ``` Self-referential structs are currently not supported with safe vanilla Rust. The only reasonable safe alternative is to expect the user to juggle 2 separate data structures which is a mess. The library solution ouroboros is expensive to compile due to its use of procedural macros. This alternative is `no_std`, uses no proc-macros, some self contained unsafe and works on stable Rust, and is miri tested. With a total of less than 300 lines of implementation code, which consists mostly of type and trait implementations, this crate aims to be a good minimal solution to the problem of self-referential structs. It has undergone [community code review](https://users.rust-lang.org/t/experimental-safe-to-use-proc-macro-free-self-referential-structs-in-stable-rust/52775) from experienced Rust users. ### Fast compile times ``` $ rm -rf target && cargo +nightly build -Z timings Compiling self_cell v0.9.0 Completed self_cell v0.9.0 in 0.2s ``` Because it does **not** use proc-macros, and has 0 dependencies compile-times are fast. Measurements done on a slow laptop. ### A motivating use case ```rust use self_cell::self_cell; #[derive(Debug, Eq, PartialEq)] struct Ast<'a>(pub Vec<&'a str>); self_cell!( struct AstCell { owner: String, #[covariant] dependent: Ast, } impl {Debug, Eq, PartialEq} ); fn build_ast_cell(code: &str) -> AstCell { // Create owning String on stack. let pre_processed_code = code.trim().to_string(); // Move String into AstCell, then build Ast inplace. AstCell::new( pre_processed_code, |code| Ast(code.split(' ').filter(|word| word.len() > 1).collect()) ) } fn main() { let ast_cell = build_ast_cell("fox = cat + dog"); println!("ast_cell -> {:?}", &ast_cell); println!("ast_cell.borrow_owner() -> {:?}", ast_cell.borrow_owner()); println!("ast_cell.borrow_dependent().0[1] -> {:?}", ast_cell.borrow_dependent().0[1]); } ``` ``` $ cargo run ast_cell -> AstCell { owner: "fox = cat + dog", dependent: Ast(["fox", "cat", "dog"]) } ast_cell.borrow_owner() -> "fox = cat + dog" ast_cell.borrow_dependent().0[1] -> "cat" ``` There is no way in safe Rust to have an API like `build_ast_cell`, as soon as `Ast` depends on stack variables like `pre_processed_code` you can't return the value out of the function anymore. You could move the pre-processing into the caller but that gets ugly quickly because you can't encapsulate things anymore. Note this is a somewhat niche use case, self-referential structs should only be used when there is no good alternative. Under the hood, it heap allocates a struct which it initializes first by moving the owner value to it and then using the reference to this now Pin/Immovable owner to construct the dependent inplace next to it. This makes it safe to move the generated SelfCell but you have to pay for the heap allocation. See the documentation for a more in-depth API overview and advanced examples: https://docs.rs/self_cell ### Installing [See cargo docs](https://doc.rust-lang.org/cargo/guide/). ## Running the tests ``` cargo test cargo miri test ``` ### Related projects - [ouroboros](https://github.com/joshua-maros/ouroboros) - [rental](https://github.com/jpernst/rental) | soundness issues (tests fail with recent miri versions) and [deprecated](https://github.com/jpernst/rental#warning-this-crate-is-no-longer-maintained-or-supported) - [Schroedinger](https://github.com/dureuill/sc) | [soundness issues](https://github.com/dureuill/sc/issues/1) - [owning_ref](https://github.com/Kimundi/owning-ref-rs) | [soundness issues](https://rustsec.org/advisories/RUSTSEC-2022-0040.html) and [seems unmaintained](https://github.com/Kimundi/owning-ref-rs/issues/81) - [ghost-cell](https://github.com/matthieu-m/ghost-cell) - [qcell](https://github.com/uazu/qcell/) - [selfref](https://docs.rs/selfref) ## Min required rustc version By default the minimum required rustc version is 1.51. There is an optional feature you can enable called "old_rust" that enables support down to rustc version 1.36. However this requires polyfilling std library functionality for older rustc with technically UB versions. Testing does not show older rustc versions (ab)using this. Use at your own risk. Using the `async_builder` option requires Rust 1.85 or newer. The minimum versions are best-effort and may change with any new major release. ## Contributing Please respect the [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) when contributing. ## Versioning We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/Voultapher/self_cell/tags). ## Authors * **Lukas Bergdoll** - *Initial work* - [Voultapher](https://github.com/Voultapher) See also the list of [contributors](https://github.com/Voultapher/self_cell/contributors) who participated in this project. ## License This project is dual licensed under the Apache License Version 2.0 OR GNU General Public License Version 2.0 - see the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-GPLv2](LICENSE-GPLv2) for details. self_cell-1.2.1/src/lib.rs000064400000000000000000000737751046102023000135030ustar 00000000000000//! # Overview //! //! `self_cell` provides one macro-rules macro: [`self_cell`]. With this macro //! you can create self-referential structs that are safe-to-use in stable Rust, //! without leaking the struct internal lifetime. //! //! In a nutshell, the API looks *roughly* like this: //! //! ```ignore //! // User code: //! //! self_cell!( //! struct NewStructName { //! owner: Owner, //! //! #[covariant] //! dependent: Dependent, //! } //! //! impl {Debug} //! ); //! //! // Generated by macro: //! //! struct NewStructName(...); //! //! impl NewStructName { //! fn new( //! owner: Owner, //! dependent_builder: impl for<'a> ::core::ops::FnOnce(&'a Owner) -> Dependent<'a> //! ) -> NewStructName { ... } //! fn borrow_owner<'a>(&'a self) -> &'a Owner { ... } //! fn borrow_dependent<'a>(&'a self) -> &'a Dependent<'a> { ... } //! [...] //! // See the macro level documentation for a list of all generated functions, //! // and other possible options, e.g. async builder support, section "Generated API". //! //! } //! //! impl Debug for NewStructName { ... } //! ``` //! //! Self-referential structs are currently not supported with safe vanilla Rust. //! The only reasonable safe alternative is to have the user juggle 2 separate //! data structures which is a mess. The library solution ouroboros is expensive //! to compile due to its use of procedural macros. //! //! This alternative is `no_std`, uses no proc-macros, some self contained //! unsafe and works on stable Rust, and is miri tested. With a total of less //! than 300 lines of implementation code, which consists mostly of type and //! trait implementations, this crate aims to be a good minimal solution to the //! problem of self-referential structs. //! //! It has undergone [community code //! review](https://users.rust-lang.org/t/experimental-safe-to-use-proc-macro-free-self-referential-structs-in-stable-rust/52775) //! from experienced Rust users. //! //! ### Fast compile times //! //! ```txt //! $ rm -rf target && cargo +nightly build -Z timings //! //! Compiling self_cell v0.7.0 //! Completed self_cell v0.7.0 in 0.2s //! ``` //! //! Because it does **not** use proc-macros, and has 0 dependencies //! compile-times are fast. //! //! Measurements done on a slow laptop. //! //! ### A motivating use case //! //! ```rust //! use self_cell::self_cell; //! //! #[derive(Debug, Eq, PartialEq)] //! struct Ast<'a>(pub Vec<&'a str>); //! //! self_cell!( //! struct AstCell { //! owner: String, //! //! #[covariant] //! dependent: Ast, //! } //! //! impl {Debug, Eq, PartialEq} //! ); //! //! fn build_ast_cell(code: &str) -> AstCell { //! // Create owning String on stack. //! let pre_processed_code = code.trim().to_string(); //! //! // Move String into AstCell, then build Ast inplace. //! AstCell::new( //! pre_processed_code, //! |code| Ast(code.split(' ').filter(|word| word.len() > 1).collect()) //! ) //! } //! //! fn main() { //! let ast_cell = build_ast_cell("fox = cat + dog"); //! //! println!("ast_cell -> {:?}", &ast_cell); //! println!("ast_cell.borrow_owner() -> {:?}", ast_cell.borrow_owner()); //! println!("ast_cell.borrow_dependent().0[1] -> {:?}", ast_cell.borrow_dependent().0[1]); //! } //! ``` //! //! ```txt //! $ cargo run //! //! ast_cell -> AstCell { owner: "fox = cat + dog", dependent: Ast(["fox", "cat", "dog"]) } //! ast_cell.borrow_owner() -> "fox = cat + dog" //! ast_cell.borrow_dependent().0[1] -> "cat" //! ``` //! //! There is no way in safe Rust to have an API like `build_ast_cell`, as soon //! as `Ast` depends on stack variables like `pre_processed_code` you can't //! return the value out of the function anymore. You could move the //! pre-processing into the caller but that gets ugly quickly because you can't //! encapsulate things anymore. Note this is a somewhat niche use case, //! self-referential structs should only be used when there is no good //! alternative. //! //! Under the hood, it heap allocates a struct which it initializes first by //! moving the owner value to it and then using the reference to this now //! Pin/Immovable owner to construct the dependent inplace next to it. This //! makes it safe to move the generated SelfCell but you have to pay for the //! heap allocation. //! //! See the documentation for [`self_cell`] to dive further into the details. //! //! Or take a look at the advanced examples: //! - [Example how to handle dependent construction that can fail](https://github.com/Voultapher/self_cell/tree/main/examples/fallible_dependent_construction) //! //! - [How to build a lazy AST with self_cell](https://github.com/Voultapher/self_cell/tree/main/examples/lazy_ast) //! //! - [How to handle dependents that take a mutable reference](https://github.com/Voultapher/self_cell/tree/main/examples/mut_ref_to_owner_in_builder) see also [`MutBorrow`] //! //! - [How to use an owner type with lifetime](https://github.com/Voultapher/self_cell/tree/main/examples/owner_with_lifetime) //! //! - [How to build the dependent with an async function](https://github.com/Voultapher/self_cell/tree/main/examples/async_builder) //! //! ### Min required rustc version //! //! By default the minimum required rustc version is 1.51. //! //! There is an optional feature you can enable called "old_rust" that enables //! support down to rustc version 1.36. However this requires polyfilling std //! library functionality for older rustc with technically UB versions. Testing //! does not show older rustc versions (ab)using this. Use at your own risk. //! //! The minimum versions are a best effor and may change with any new major //! release. #![no_std] #[doc(hidden)] pub extern crate alloc; #[doc(hidden)] pub mod unsafe_self_cell; /// This macro declares a new struct of `$StructName` and implements traits /// based on `$AutomaticDerive`. /// /// ### Example: /// /// ```rust /// use self_cell::self_cell; /// /// #[derive(Debug, Eq, PartialEq)] /// struct Ast<'a>(Vec<&'a str>); /// /// self_cell!( /// #[doc(hidden)] /// struct PackedAstCell { /// owner: String, /// /// #[covariant] /// dependent: Ast, /// } /// /// impl {Debug, PartialEq, Eq, Hash} /// ); /// ``` /// /// See the crate overview to get a get an overview and a motivating example. /// /// ### Generated API: /// /// The macro implements these constructors: /// /// ```ignore /// fn new( /// owner: $Owner, /// dependent_builder: impl for<'a> ::core::ops::FnOnce(&'a $Owner) -> $Dependent<'a> /// ) -> Self /// ``` /// /// ```ignore /// fn try_new( /// owner: $Owner, /// dependent_builder: impl for<'a> ::core::ops::FnOnce(&'a $Owner) -> Result<$Dependent<'a>, Err> /// ) -> Result /// ``` /// /// ```ignore /// fn try_new_or_recover( /// owner: $Owner, /// dependent_builder: impl for<'a> ::core::ops::FnOnce(&'a $Owner) -> Result<$Dependent<'a>, Err> /// ) -> Result /// ``` /// /// The macro implements these methods: /// /// ```ignore /// fn borrow_owner<'a>(&'a self) -> &'a $Owner /// ``` /// /// ```ignore /// // Only available if dependent is covariant. /// fn borrow_dependent<'a>(&'a self) -> &'a $Dependent<'a> /// ``` /// /// ```ignore /// fn with_dependent<'outer_fn, Ret>( /// &'outer_fn self, /// func: impl for<'a> ::core::ops::FnOnce(&'a $Owner, &'outer_fn $Dependent<'a> /// ) -> Ret) -> Ret /// ``` /// /// ```ignore /// fn with_dependent_mut<'outer_fn, Ret>( /// &'outer_fn mut self, /// func: impl for<'a> ::core::ops::FnOnce(&'a $Owner, &'outer_fn mut $Dependent<'a>) -> Ret /// ) -> Ret /// ``` /// /// ```ignore /// fn into_owner(self) -> $Owner /// ``` /// /// /// ### Parameters: /// /// - `$Vis:vis struct $StructName:ident` Name of the struct that will be /// declared, this needs to be unique for the relevant scope. Example: `struct /// AstCell` or `pub struct AstCell`. `$Vis` can be used to mark the struct /// and all functions implemented by the macro as public. /// /// `$(#[$StructMeta:meta])*` allows you specify further meta items for this /// struct, eg. `#[doc(hidden)] struct AstCell`. /// /// - `$Owner:ty` Type of owner. This has to have a `'static` lifetime. Example: /// `String`. /// /// - `$Dependent:ident` Name of the dependent type without specified lifetime. /// This can't be a nested type name. As workaround either create a type alias /// `type Dep<'a> = Option>;` or create a new-type `struct /// Dep<'a>(Option>);`. Example: `Ast`. /// /// `$Covariance:ident` Marker declaring if `$Dependent` is /// [covariant](https://doc.rust-lang.org/nightly/nomicon/subtyping.html). /// Possible Values: /// /// * **covariant**: This generates the direct reference accessor function /// `borrow_dependent`. This is only safe to do if this compiles `fn /// _assert_covariance<'x: 'y, 'y>(x: &'y $Dependent<'x>) -> &'y $Dependent<'y> /// {x}`. Otherwise you could choose a lifetime that is too short for types /// with interior mutability like `Cell`, which can lead to UB in safe code. /// Which would violate the promise of this library that it is safe-to-use. /// If you accidentally mark a type that is not covariant as covariant, you /// will get a compile time error. /// /// * **not_covariant**: This generates no additional code but you can use the /// `with_dependent` function. See [How to build a lazy AST with /// self_cell](https://github.com/Voultapher/self_cell/tree/main/examples/lazy_ast) /// for a usage example. /// /// In both cases you can use the `with_dependent_mut` function to mutate the /// dependent value. This is safe to do because notionally you are replacing /// pointers to a value not the other way around. /// /// `#[$Covariance:ident, async_builder]` Optional marker that tells the macro to /// generate `async` construction functions. `new`, `try_new` and `try_new_or_recover` /// will all be `async` functions taking `async` closures as `dependent_builder` /// functions. /// /// - `impl {$($AutomaticDerive:ident),*},` Optional comma separated list of /// optional automatic trait implementations. Possible Values: /// /// * **Debug**: Prints the debug representation of owner and dependent. /// Example: `AstCell { owner: "fox = cat + dog", dependent: Ast(["fox", /// "cat", "dog"]) }` /// /// * **PartialEq**: Logic `*self.borrow_owner() == *other.borrow_owner()`, /// this assumes that `Dependent<'a>::From<&'a Owner>` is deterministic, so /// that only comparing owner is enough. /// /// * **Eq**: Will implement the trait marker `Eq` for `$StructName`. Beware /// if you select this `Eq` will be implemented regardless if `$Owner` /// implements `Eq`, that's an unfortunate technical limitation. /// /// * **Hash**: Logic `self.borrow_owner().hash(state);`, this assumes that /// `Dependent<'a>::From<&'a Owner>` is deterministic, so that only hashing /// owner is enough. /// /// All `AutomaticDerive` are optional and you can implement you own version /// of these traits. The declared struct is part of your module and you are /// free to implement any trait in any way you want. Access to the unsafe /// internals is only possible via unsafe functions, so you can't accidentally /// use them in safe code. /// /// There is limited nested cell support. Eg, having an owner with non static /// references. Eg `struct ChildCell<'a> { owner: &'a String, ...`. You can /// use any lifetime name you want, except `_q` and only a single lifetime is /// supported, and can only be used in the owner. Due to macro_rules /// limitations, no `AutomaticDerive` are supported if an owner lifetime is /// provided. /// #[macro_export] macro_rules! self_cell { ( $(#[$StructMeta:meta])* $Vis:vis struct $StructName:ident $(<$OwnerLifetime:lifetime>)? { owner: $Owner:ty, #[$Covariance:ident $(, $AsyncBuilder:ident)?] dependent: $Dependent:ident, } $(impl {$($AutomaticDerive:ident),*})? ) => { #[repr(transparent)] $(#[$StructMeta])* $Vis struct $StructName $(<$OwnerLifetime>)? { unsafe_self_cell: $crate::unsafe_self_cell::UnsafeSelfCell< $StructName$(<$OwnerLifetime>)?, $Owner, $Dependent<'static> >, $(owner_marker: $crate::_covariant_owner_marker!($Covariance, $OwnerLifetime) ,)? } impl <$($OwnerLifetime)?> $StructName <$($OwnerLifetime)?> { $crate::_self_cell_new!($Vis, $Owner $(=> $OwnerLifetime)?, $Dependent $(, $AsyncBuilder)?); $crate::_self_cell_try_new!($Vis, $Owner $(=> $OwnerLifetime)?, $Dependent $(, $AsyncBuilder)?); $crate::_self_cell_try_new_or_recover!($Vis, $Owner $(=> $OwnerLifetime)?, $Dependent $(, $AsyncBuilder)?); /// Borrows owner. $Vis fn borrow_owner<'_q>(&'_q self) -> &'_q $Owner { unsafe { self.unsafe_self_cell.borrow_owner::<$Dependent<'_q>>() } } /// Calls given closure `func` with a shared reference to dependent. $Vis fn with_dependent<'outer_fn, Ret>( &'outer_fn self, func: impl for<'_q> ::core::ops::FnOnce(&'_q $Owner, &'outer_fn $Dependent<'_q> ) -> Ret) -> Ret { unsafe { func( self.unsafe_self_cell.borrow_owner::<$Dependent>(), self.unsafe_self_cell.borrow_dependent() ) } } /// Calls given closure `func` with an unique reference to dependent. $Vis fn with_dependent_mut<'outer_fn, Ret>( &'outer_fn mut self, func: impl for<'_q> ::core::ops::FnOnce(&'_q $Owner, &'outer_fn mut $Dependent<'_q>) -> Ret ) -> Ret { let (owner, dependent) = unsafe { self.unsafe_self_cell.borrow_mut() }; func(owner, dependent) } $crate::_covariant_access!($Covariance, $Vis, $Dependent); /// Consumes `self` and returns the the owner. $Vis fn into_owner(self) -> $Owner { // This is only safe to do with repr(transparent). let unsafe_self_cell = unsafe { ::core::mem::transmute::< Self, $crate::unsafe_self_cell::UnsafeSelfCell< $StructName$(<$OwnerLifetime>)?, $Owner, $Dependent<'static> > >(self) }; let owner = unsafe { unsafe_self_cell.into_owner::<$Dependent>() }; owner } } impl $(<$OwnerLifetime>)? Drop for $StructName $(<$OwnerLifetime>)? { fn drop(&mut self) { unsafe { self.unsafe_self_cell.drop_joined::<$Dependent>(); } } } // The user has to choose which traits can and should be automatically // implemented for the cell. $($( $crate::_impl_automatic_derive!($AutomaticDerive, $StructName); )*)* }; } #[doc(hidden)] #[macro_export] macro_rules! _covariant_access { (covariant, $Vis:vis, $Dependent:ident) => { /// Borrows dependent. $Vis fn borrow_dependent<'_q>(&'_q self) -> &'_q $Dependent<'_q> { fn _assert_covariance<'x: 'y, 'y>(x: &'y $Dependent<'x>) -> &'y $Dependent<'y> { // This function only compiles for covariant types. x // Change the macro invocation to not_covariant. } unsafe { self.unsafe_self_cell.borrow_dependent() } } }; (not_covariant, $Vis:vis, $Dependent:ident) => { // For types that are not covariant it's unsafe to allow // returning direct references. // For example a lifetime that is too short could be chosen: // See https://github.com/Voultapher/self_cell/issues/5 }; ($x:ident, $Vis:vis, $Dependent:ident) => { compile_error!("This macro only accepts `covariant` or `not_covariant`"); }; } #[doc(hidden)] #[macro_export] macro_rules! _covariant_owner_marker { (covariant, $OwnerLifetime:lifetime) => { // Ensure that contravariant owners don't imply covariance // over the dependent. See issue https://github.com/Voultapher/self_cell/issues/18 ::core::marker::PhantomData<&$OwnerLifetime ()> }; (not_covariant, $OwnerLifetime:lifetime) => { // See the discussion in https://github.com/Voultapher/self_cell/pull/29 // // If the dependent is non_covariant, mark the owner as invariant over its // lifetime. Otherwise unsound use is possible. ::core::marker::PhantomData &$OwnerLifetime ()> }; ($x:ident, $OwnerLifetime:lifetime) => { compile_error!("This macro only accepts `covariant` or `not_covariant`"); }; } #[doc(hidden)] #[macro_export] macro_rules! _covariant_owner_marker_ctor { ($OwnerLifetime:lifetime) => { // Helper to optionally expand into PhantomData for construction. ::core::marker::PhantomData }; } #[doc(hidden)] #[macro_export] macro_rules! _self_cell_new { ($Vis:vis, $Owner:ty $(=> $OwnerLifetime:lifetime)?, $Dependent:ident) => { /// Constructs a new self-referential struct. /// /// The provided `owner` will be moved into a heap allocated box. Followed by construction /// of the dependent value, by calling `dependent_builder` with a shared reference to the /// owner that remains valid for the lifetime of the constructed struct. $Vis fn new( owner: $Owner, dependent_builder: impl for<'_q> ::core::ops::FnOnce(&'_q $Owner) -> $Dependent<'_q> ) -> Self { type JoinedCell<'_q $(, $OwnerLifetime)?> = $crate::unsafe_self_cell::JoinedCell<$Owner, $Dependent<'_q>>; // unsafe placed here to make sure the body macro can't be abused. unsafe { $crate::_self_cell_new_body!(JoinedCell, owner $(=> $OwnerLifetime)?, dependent_builder) } } }; ($Vis:vis, $Owner:ty $(=> $OwnerLifetime:lifetime)?, $Dependent:ident, async_builder) => { /// Constructs a new self-referential struct. /// /// The provided `owner` will be moved into a heap allocated box. Followed by construction /// of the dependent value, by calling the async closure `dependent_builder` with a shared /// reference to the owner that remains valid for the lifetime of the constructed struct. $Vis async fn new( owner: $Owner, dependent_builder: impl for<'_q> ::core::ops::AsyncFnOnce(&'_q $Owner) -> $Dependent<'_q> ) -> Self { type JoinedCell<'_q $(, $OwnerLifetime)?> = $crate::unsafe_self_cell::JoinedCell<$Owner, $Dependent<'_q>>; // unsafe placed here to make sure the body macro can't be abused. unsafe { $crate::_self_cell_new_body!(JoinedCell, owner $(=> $OwnerLifetime)?, dependent_builder, async_builder) } } }; ($Vis:vis, $Owner:ty, $Dependent:ident, $x:ident) => { compile_error!("This macro only accepts `async_builder`"); }; } #[doc(hidden)] #[macro_export] macro_rules! _self_cell_new_body { ($JoinedCell:ty, $owner:expr $(=> $OwnerLifetime:lifetime)?, $dependent_builder:expr $(, $AsyncBuilder:ident)?) => {{ // All this has to happen here, because there is not good way // of passing the appropriate logic into UnsafeSelfCell::new // short of assuming Dependent<'static> is the same as // Dependent<'_q>, which I'm not confident is safe. // For this API to be safe there has to be no safe way to // capture additional references in `dependent_builder` and then // return them as part of Dependent. Eg. it should be impossible // to express: '_q should outlive 'x here `fn // bad<'_q>(outside_ref: &'_q String) -> impl for<'x> ::core::ops::FnOnce(&'x // Owner) -> Dependent<'x>`. let layout = $crate::alloc::alloc::Layout::new::<$JoinedCell>(); assert!(layout.size() != 0); let joined_void_ptr = ::core::ptr::NonNull::new($crate::alloc::alloc::alloc(layout)).unwrap(); let mut joined_ptr = joined_void_ptr.cast::<$JoinedCell>(); let (owner_ptr, dependent_ptr) = <$JoinedCell>::_field_pointers(joined_ptr.as_ptr()); // Move owner into newly allocated space. owner_ptr.write($owner); // Drop guard that cleans up should building the dependent panic. let drop_guard = $crate::unsafe_self_cell::OwnerAndCellDropGuard::new(joined_ptr); // Initialize dependent with owner reference in final place. dependent_ptr.write($crate::_await_opt!($dependent_builder(&*owner_ptr) $(, $AsyncBuilder)?)); ::core::mem::forget(drop_guard); Self { unsafe_self_cell: $crate::unsafe_self_cell::UnsafeSelfCell::new( joined_void_ptr, ), $(owner_marker: $crate::_covariant_owner_marker_ctor!($OwnerLifetime) ,)? } }} } #[doc(hidden)] #[macro_export] macro_rules! _self_cell_try_new { ($Vis:vis, $Owner:ty $(=> $OwnerLifetime:lifetime)?, $Dependent:ident) => { /// Constructs a new self-referential struct or returns an error. /// /// Consumes owner on error. $Vis fn try_new( owner: $Owner, dependent_builder: impl for<'_q> ::core::ops::FnOnce(&'_q $Owner) -> ::core::result::Result<$Dependent<'_q>, Err> ) -> ::core::result::Result { type JoinedCell<'_q $(, $OwnerLifetime)?> = $crate::unsafe_self_cell::JoinedCell<$Owner, $Dependent<'_q>>; // unsafe placed here to make sure the body macro can't be abused. unsafe { $crate::_self_cell_try_new_body!(JoinedCell, owner $(=> $OwnerLifetime)?, dependent_builder) } } }; ($Vis:vis, $Owner:ty $(=> $OwnerLifetime:lifetime)?, $Dependent:ident, async_builder) => { /// Constructs a new self-referential struct or returns an error. /// /// Consumes owner on error. $Vis async fn try_new( owner: $Owner, dependent_builder: impl for<'_q> ::core::ops::AsyncFnOnce(&'_q $Owner) -> ::core::result::Result<$Dependent<'_q>, Err> ) -> ::core::result::Result { type JoinedCell<'_q $(, $OwnerLifetime)?> = $crate::unsafe_self_cell::JoinedCell<$Owner, $Dependent<'_q>>; // unsafe placed here to make sure the body macro can't be abused. unsafe { $crate::_self_cell_try_new_body!(JoinedCell, owner $(=> $OwnerLifetime)?, dependent_builder, async_builder) } } }; ($Vis:vis, $Owner:ty, $Dependent:ident, $x:ident) => { compile_error!("This macro only accepts `async_builder`"); }; } #[doc(hidden)] #[macro_export] macro_rules! _self_cell_try_new_body { ($JoinedCell:ty, $owner:expr $(=> $OwnerLifetime:lifetime)?, $dependent_builder:expr $(, $AsyncBuilder:ident)?) => {{ // See fn new for more explanation. let layout = $crate::alloc::alloc::Layout::new::<$JoinedCell>(); assert!(layout.size() != 0); let joined_void_ptr = ::core::ptr::NonNull::new($crate::alloc::alloc::alloc(layout)).unwrap(); let mut joined_ptr = joined_void_ptr.cast::<$JoinedCell>(); let (owner_ptr, dependent_ptr) = <$JoinedCell>::_field_pointers(joined_ptr.as_ptr()); // Move owner into newly allocated space. owner_ptr.write($owner); // Drop guard that cleans up should building the dependent panic. let mut drop_guard = $crate::unsafe_self_cell::OwnerAndCellDropGuard::new(joined_ptr); match $crate::_await_opt!($dependent_builder(&*owner_ptr) $(, $AsyncBuilder)?) { ::core::result::Result::Ok(dependent) => { dependent_ptr.write(dependent); ::core::mem::forget(drop_guard); ::core::result::Result::Ok(Self { unsafe_self_cell: $crate::unsafe_self_cell::UnsafeSelfCell::new( joined_void_ptr, ), $(owner_marker: $crate::_covariant_owner_marker_ctor!($OwnerLifetime) ,)? }) } ::core::result::Result::Err(err) => ::core::result::Result::Err(err) } }} } #[doc(hidden)] #[macro_export] macro_rules! _self_cell_try_new_or_recover { ($Vis:vis, $Owner:ty $(=> $OwnerLifetime:lifetime)?, $Dependent:ident) => { /// Constructs a new self-referential struct or returns an error. /// /// Returns owner and error as tuple on error. $Vis fn try_new_or_recover( owner: $Owner, dependent_builder: impl for<'_q> ::core::ops::FnOnce(&'_q $Owner) -> ::core::result::Result<$Dependent<'_q>, Err> ) -> ::core::result::Result { type JoinedCell<'_q $(, $OwnerLifetime)?> = $crate::unsafe_self_cell::JoinedCell<$Owner, $Dependent<'_q>>; // unsafe placed here to make sure the body macro can't be abused. unsafe { $crate::_self_cell_try_new_or_recover_body!(JoinedCell, owner $(=> $OwnerLifetime)?, dependent_builder) } } }; ($Vis:vis, $Owner:ty $(=> $OwnerLifetime:lifetime)?, $Dependent:ident, async_builder) => { /// Constructs a new self-referential struct or returns an error. /// /// Returns owner and error as tuple on error. $Vis async fn try_new_or_recover( owner: $Owner, dependent_builder: impl for<'_q> ::core::ops::AsyncFnOnce(&'_q $Owner) -> ::core::result::Result<$Dependent<'_q>, Err> ) -> ::core::result::Result { type JoinedCell<'_q $(, $OwnerLifetime)?> = $crate::unsafe_self_cell::JoinedCell<$Owner, $Dependent<'_q>>; // unsafe placed here to make sure the body macro can't be abused. unsafe { $crate::_self_cell_try_new_or_recover_body!(JoinedCell, owner $(=> $OwnerLifetime)?, dependent_builder, async_builder) } } }; ($Vis:vis, $Owner:ty, $Dependent:ident, $x:ident) => { compile_error!("This macro only accepts `async_builder`"); }; } #[doc(hidden)] #[macro_export] macro_rules! _self_cell_try_new_or_recover_body { ($JoinedCell:ty, $owner:expr $(=> $OwnerLifetime:lifetime)?, $dependent_builder:expr $(, $AsyncBuilder:ident)?) => {{ let layout = $crate::alloc::alloc::Layout::new::<$JoinedCell>(); assert!(layout.size() != 0); let joined_void_ptr = ::core::ptr::NonNull::new($crate::alloc::alloc::alloc(layout)).unwrap(); let mut joined_ptr = joined_void_ptr.cast::<$JoinedCell>(); let (owner_ptr, dependent_ptr) = <$JoinedCell>::_field_pointers(joined_ptr.as_ptr()); // Move owner into newly allocated space. owner_ptr.write($owner); // Drop guard that cleans up should building the dependent panic. let mut drop_guard = $crate::unsafe_self_cell::OwnerAndCellDropGuard::new(joined_ptr); match $crate::_await_opt!($dependent_builder(&*owner_ptr) $(, $AsyncBuilder)?) { ::core::result::Result::Ok(dependent) => { dependent_ptr.write(dependent); ::core::mem::forget(drop_guard); ::core::result::Result::Ok(Self { unsafe_self_cell: $crate::unsafe_self_cell::UnsafeSelfCell::new( joined_void_ptr, ), $(owner_marker: $crate::_covariant_owner_marker_ctor!($OwnerLifetime) ,)? }) } ::core::result::Result::Err(err) => { // In contrast to into_owner ptr::read, here no dependent // ever existed in this function and so we are sure its // drop impl can't access owner after the read. // And err can't return a reference to owner. let owner_on_err = ::core::ptr::read(owner_ptr); // Allowing drop_guard to finish would let it double free owner. // So we dealloc the JoinedCell here manually. ::core::mem::forget(drop_guard); $crate::alloc::alloc::dealloc(joined_void_ptr.as_ptr(), layout); ::core::result::Result::Err((owner_on_err, err)) } } }} } #[doc(hidden)] #[macro_export] macro_rules! _await_opt { ($val:expr) => { $val }; ($future:expr, async_builder) => { $future.await }; ($v:expr, $x:ident) => { compile_error!("This macro only accepts `async_builder`"); }; } #[doc(hidden)] #[macro_export] macro_rules! _impl_automatic_derive { (Debug, $StructName:ident) => { impl ::core::fmt::Debug for $StructName { fn fmt( &self, fmt: &mut ::core::fmt::Formatter, ) -> ::core::result::Result<(), ::core::fmt::Error> { self.with_dependent(|owner, dependent| { fmt.debug_struct(stringify!($StructName)) .field("owner", owner) .field("dependent", dependent) .finish() }) } } }; (PartialEq, $StructName:ident) => { impl ::core::cmp::PartialEq for $StructName { fn eq(&self, other: &Self) -> bool { *self.borrow_owner() == *other.borrow_owner() } } }; (Eq, $StructName:ident) => { // TODO this should only be allowed if owner is Eq. impl ::core::cmp::Eq for $StructName {} }; (Hash, $StructName:ident) => { impl ::core::hash::Hash for $StructName { fn hash(&self, state: &mut H) { self.borrow_owner().hash(state); } } }; ($x:ident, $StructName:ident) => { compile_error!(concat!( "No automatic trait impl for trait: ", stringify!($x) )); }; } pub use unsafe_self_cell::MutBorrow; self_cell-1.2.1/src/unsafe_self_cell.rs000064400000000000000000000262011046102023000162040ustar 00000000000000#![allow(clippy::missing_safety_doc, clippy::needless_lifetimes)] use core::cell::UnsafeCell; use core::marker::PhantomData; use core::mem; use core::ptr::{drop_in_place, read, NonNull}; use core::sync::atomic::{AtomicBool, Ordering}; extern crate alloc; use alloc::alloc::{dealloc, Layout}; // Self referential structs are currently not supported with safe vanilla Rust. // The only reasonable safe alternative is to expect the user to juggle 2 separate // data structures which is a mess. The library solution rental is both no longer // maintained and really heavy to compile. So begrudgingly I rolled my own version. // These are some of the core invariants we require for this to be safe to use. // // 1. owner is initialized when UnsafeSelfCell is constructed. // 2. owner is NEVER changed again. // 3. The pointer to owner and dependent never changes, even when moved. // 4. The only access to owner and dependent is as immutable reference. // 5. owner lives longer than dependent. #[doc(hidden)] pub struct JoinedCell { pub owner: Owner, pub dependent: Dependent, } // Library controlled struct that marks all accesses as unsafe. // Because the macro generated struct impl can be extended, could be unsafe. #[doc(hidden)] pub struct UnsafeSelfCell { joined_void_ptr: NonNull, // ContainedIn is necessary for type safety since we don't fully // prohibit access to the UnsafeSelfCell; swapping between different // structs can be unsafe otherwise, see Issue #17. contained_in_marker: PhantomData, owner_marker: PhantomData, // DependentStatic is only used to correctly derive Send and Sync. dependent_marker: PhantomData, } impl UnsafeSelfCell { pub unsafe fn new(joined_void_ptr: NonNull) -> Self { Self { joined_void_ptr, contained_in_marker: PhantomData, owner_marker: PhantomData, dependent_marker: PhantomData, } } // Calling any of these *unsafe* functions with the wrong Dependent type is UB. pub unsafe fn borrow_owner<'a, Dependent>(&'a self) -> &'a Owner { let joined_ptr = self.joined_void_ptr.cast::>(); &(*joined_ptr.as_ptr()).owner } pub unsafe fn borrow_dependent<'a, Dependent>(&'a self) -> &'a Dependent { let joined_ptr = self.joined_void_ptr.cast::>(); &(*joined_ptr.as_ptr()).dependent } pub unsafe fn borrow_mut<'a, Dependent>(&'a mut self) -> (&'a Owner, &'a mut Dependent) { let joined_ptr = self.joined_void_ptr.cast::>(); // This function used to return `&'a mut JoinedCell`. // It now creates two references to the fields instead to avoid claiming mutable access // to the whole `JoinedCell` (including the owner!) here. ( &(*joined_ptr.as_ptr()).owner, &mut (*joined_ptr.as_ptr()).dependent, ) } // Any subsequent use of this struct other than dropping it is UB. pub unsafe fn drop_joined(&mut self) { let joined_ptr = self.joined_void_ptr.cast::>(); // Also used in case drop_in_place(...dependent) fails let _guard = OwnerAndCellDropGuard { joined_ptr }; // IMPORTANT dependent must be dropped before owner. // We don't want to rely on an implicit order of struct fields. // So we drop the struct, field by field manually. drop_in_place(&mut (*joined_ptr.as_ptr()).dependent); // Dropping owner // and deallocating // due to _guard at end of scope. } pub unsafe fn into_owner(self) -> Owner { let joined_ptr = self.joined_void_ptr.cast::>(); // In case drop_in_place(...dependent) fails let drop_guard = OwnerAndCellDropGuard::new(joined_ptr); // Drop dependent drop_in_place(&mut (*joined_ptr.as_ptr()).dependent); mem::forget(drop_guard); let owner_ptr: *const Owner = &(*joined_ptr.as_ptr()).owner; // Move owner out so it can be returned. // Must not read before dropping dependent!! (Which happened above.) let owner = read(owner_ptr); // Deallocate JoinedCell let layout = Layout::new::>(); dealloc(self.joined_void_ptr.as_ptr(), layout); owner } } unsafe impl Send for UnsafeSelfCell where // Only derive Send if Owner and DependentStatic is also Send Owner: Send, DependentStatic: Send, { } unsafe impl Sync for UnsafeSelfCell where // Only derive Sync if Owner and DependentStatic is also Sync Owner: Sync, DependentStatic: Sync, { } // This struct is used to safely deallocate only the owner if dependent // construction fails. // // mem::forget it once it's no longer needed or dtor will be UB. #[doc(hidden)] pub struct OwnerAndCellDropGuard { joined_ptr: NonNull>, } impl OwnerAndCellDropGuard { pub unsafe fn new(joined_ptr: NonNull>) -> Self { Self { joined_ptr } } } impl Drop for OwnerAndCellDropGuard { fn drop(&mut self) { struct DeallocGuard { ptr: *mut u8, layout: Layout, } impl Drop for DeallocGuard { fn drop(&mut self) { unsafe { dealloc(self.ptr, self.layout) } } } // Deallocate even when the drop_in_place(...owner) panics let _guard = DeallocGuard { ptr: self.joined_ptr.as_ptr() as *mut u8, layout: Layout::new::>(), }; unsafe { // We must only drop owner and the struct itself, // The whole point of this drop guard is to clean up the partially // initialized struct should building the dependent fail. drop_in_place(&mut (*self.joined_ptr.as_ptr()).owner); } // Deallocation happens at end of scope } } // Older versions of rust do not support addr_of_mut!. What we want to do here // is to emulate the behavior of that macro by going (incorrectly) via a // reference cast. Technically this is UB, but testing does not show the older // compiler versions (ab)using this. For discussions about this behavior see // https://github.com/Voultapher/self_cell/pull/31 and // https://github.com/Voultapher/self_cell/issues/30 and // https://github.com/Voultapher/self_cell/pull/33 // // Because of 'procedural macros cannot expand to macro definitions' // we have wrap this in functions. impl JoinedCell { #[doc(hidden)] #[cfg(not(feature = "old_rust"))] pub unsafe fn _field_pointers(this: *mut Self) -> (*mut Owner, *mut Dependent) { let owner_ptr = core::ptr::addr_of_mut!((*this).owner); let dependent_ptr = core::ptr::addr_of_mut!((*this).dependent); (owner_ptr, dependent_ptr) } #[doc(hidden)] #[cfg(feature = "old_rust")] #[rustversion::since(1.51)] pub unsafe fn _field_pointers(this: *mut Self) -> (*mut Owner, *mut Dependent) { let owner_ptr = core::ptr::addr_of_mut!((*this).owner); let dependent_ptr = core::ptr::addr_of_mut!((*this).dependent); (owner_ptr, dependent_ptr) } #[doc(hidden)] #[cfg(feature = "old_rust")] #[rustversion::before(1.51)] pub unsafe fn _field_pointers(this: *mut Self) -> (*mut Owner, *mut Dependent) { // See comment above, technically this is UB. let owner_ptr = &mut (*this).owner as *mut Owner; let dependent_ptr = &mut (*this).dependent as *mut Dependent; (owner_ptr, dependent_ptr) } } /// Wrapper type that allows creating a self-referential type that hold a mutable borrow `&mut T`. /// /// Example usage: /// /// ``` /// use self_cell::{self_cell, MutBorrow}; /// /// type MutStringRef<'a> = &'a mut String; /// /// self_cell!( /// struct MutStringCell { /// owner: MutBorrow, /// /// #[covariant] /// dependent: MutStringRef, /// } /// ); /// /// let mut cell = MutStringCell::new(MutBorrow::new("abc".into()), |owner| owner.borrow_mut()); /// cell.with_dependent_mut(|_owner, dependent| { /// assert_eq!(dependent, &"abc"); /// dependent.pop(); /// assert_eq!(dependent, &"ab"); /// }); /// /// let recovered_owner: String = cell.into_owner().into_inner(); /// assert_eq!(recovered_owner, "ab"); /// ``` pub struct MutBorrow { // Private on purpose. is_locked: AtomicBool, value: UnsafeCell, } impl MutBorrow { /// Constructs a new `MutBorrow`. pub fn new(value: T) -> Self { // Use the Rust type system to model an affine type that can only go from unlocked -> locked // but never the other way around. Self { is_locked: AtomicBool::new(false), value: UnsafeCell::new(value), } } /// Obtains a mutable reference to the underlying data. /// /// This function can only sensibly be used in the builder function. Afterwards, it's impossible /// to access the inner value, with the exception of [`MutBorrow::into_inner`]. /// /// # Panics /// /// Will panic if called anywhere but in the dependent constructor. Will also panic if called /// more than once. #[allow(clippy::mut_from_ref)] pub fn borrow_mut(&self) -> &mut T { // Ensure this function can only be called once. // Relaxed should be fine, because only one thread could ever read `false` anyway, // so further synchronization is pointless. let was_locked = self.is_locked.swap(true, Ordering::Relaxed); if was_locked { panic!("Tried to access locked MutBorrow") } else { // SAFETY: `self.is_locked` starts out as locked and can never be unlocked again, which // guarantees that this function can only be called once. And the `self.value` being // private ensures that there are no other references to it. unsafe { &mut *self.value.get() } } } /// Consumes `self` and returns the wrapped value. pub fn into_inner(self) -> T { self.value.into_inner() } } // SAFETY: The reasoning why it is safe to share `MutBorrow` across threads is as follows: The // `AtomicBool` `is_locked` ensures that only ever exactly one thread can get access to the inner // value. In that sense it works like a critical section, that begins when `borrow_mut()` is called // and that ends when the outer `MutBorrow` is dropped. Once one thread acquired the unique // reference through `borrow_mut()` no other interaction with the inner value MUST ever be possible // while the outer `MutBorrow` is alive. unsafe impl Sync for MutBorrow {}