// SelfRef - Pain-free self-referential pinned types // Copyright (C) 2022 Soni L. // With help from quinedot // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #![feature(generic_associated_types)] #![no_std] //! Pain-free self-referential pinned types. //! //! This crate (currently) requires nightly, as it relies on GATs. //! //! # Example //! /// ```rust /// #![feature(generic_associated_types)] /// #![feature(pin_macro)] /// /// use core::cell::Cell; /// use core::marker::PhantomData; /// use core::pin::Pin; /// use core::pin::pin; /// /// use selfref::Holder; /// use selfref::NewWith; /// use selfref::OperateIn; /// use selfref::SelfRef; /// use selfref::opaque; /// /// struct Foo<'a, 'b: 'a> { /// foo: Cell>>, /// t: &'b str, /// } /// impl<'a, 'b> SelfRef<'a> for Foo<'a, 'b> {} /// /// struct FooKey<'b>(PhantomData<&'b str>); /// opaque! { /// impl['b] Opaque for FooKey<'b> { /// type Kind<'a> = Foo<'a, 'b>; /// } /// } /// /// fn main() { /// 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 { /// Foo { /// foo: Default::default(), /// t: self.0, /// } /// } /// } /// let stack_array: [u8; 5] = *b"hello"; /// // a non-'static &str /// let stack_str = core::str::from_utf8(&stack_array).unwrap(); /// let holder = pin!(Holder::new_with(FooBuilder(stack_str))); /// // Actually making our Foo refer to itself. /// struct SetFooRef; /// impl<'k, 'b: 'k> OperateIn<'k, FooKey<'b>> for SetFooRef { /// type Out = (); /// fn operate_in<'a>(self, foo: Pin<&'a Foo<'a, 'b>>) /// where 'k: 'a { /// foo.foo.set(Some(foo.get_ref())); /// } /// } /// holder.as_ref().operate_in(SetFooRef); /// } /// ``` use core::marker::PhantomPinned; use core::pin::Pin; use core::mem; /// A self-referential struct. /// /// # Example /// /// ```rust /// #![feature(generic_associated_types)] /// /// use core::cell::Cell; /// /// use selfref::SelfRef; /// /// struct Foo<'a> { /// foo: Cell>>, /// } /// impl<'a> SelfRef<'a> for Foo<'a> {} /// ``` pub trait SelfRef<'a> { } /// An opaqueified self-referential struct "key". /// /// # Safety /// /// This is unsafe because there are a bunch of soundness invariants that need /// to be upheld. The following list is non-exhaustive: /// /// - `Kind` must not have a `Drop` impl in any "path" that may trace back to /// the original self-referential type, if said `Drop` impl can observe /// the self-referential type. /// - We assume `Kind` has the same layout for any `'a`. This is true as of the /// time of writing this, and relies on Rust not having lifetime /// specialization. /// /// # Examples /// /// ```rust /// #![feature(generic_associated_types)] /// /// use core::cell::Cell; /// /// use selfref::SelfRef; /// use selfref::Opaque; /// /// struct Foo<'a> { /// foo: Cell>>, /// } /// impl<'a> SelfRef<'a> for Foo<'a> {} /// /// struct FooKey; /// // SAFETY: Foo has no Drop impl and has the same layout for any 'a. /// unsafe impl Opaque for FooKey { /// type Kind<'a> = Foo<'a>; /// } /// ``` pub unsafe trait Opaque { /// The actual self-referential struct. type Kind<'a>: SelfRef<'a> where Self: 'a; #[doc(hidden)] fn ub_check() { } } /// Creates an opaqueified self-referential struct "key". /// /// Safe wrapper around [`Opaque`] that checks the soundness requirements at /// compile-time. /// /// There are 2 forms of this macro. The second form accepts type parameters. /// /// Note that where bounds go after the impl block. /// /// # Examples /// /// Simple example: /// /// ```rust /// #![feature(generic_associated_types)] /// /// use core::cell::Cell; /// /// use selfref::SelfRef; /// use selfref::opaque; /// /// struct Foo<'a> { /// foo: Cell>>, /// } /// impl<'a> SelfRef<'a> for Foo<'a> {} /// /// struct FooKey; /// opaque! { /// impl Opaque for FooKey { /// type Kind<'a> = Foo<'a>; /// } /// } /// ``` /// /// Type parameters and where bounds: /// /// ```rust /// #![feature(generic_associated_types)] /// /// use core::cell::Cell; /// use core::fmt::Display; /// use core::marker::PhantomData; /// /// use selfref::SelfRef; /// use selfref::opaque; /// /// struct Foo<'a, T: Display> { /// foo: Cell>>, /// t: T, /// } /// impl<'a, T: Display> SelfRef<'a> for Foo<'a, T> {} /// /// struct FooKey(PhantomData); /// opaque! { /// impl[T] Opaque for FooKey { /// type Kind<'a> = Foo<'a, T>; /// } where T: Display /// } /// ``` #[macro_export] macro_rules! opaque { ( impl Opaque for $key:ty { type Kind<$l:lifetime> = $kind:ty; } $(where $($bounds:tt)*)? ) => { unsafe impl $crate::Opaque for $key $(where $($bounds)*)? { type Kind<$l> = $kind where Self: $l; fn ub_check() { fn ub_detect_helper( _f: impl ::core::ops::Fn( for<$l> fn([&$l (); 0]) -> $kind, for<$l> fn(&$l $kind) ) ) $(where $($bounds)*)? { } ub_detect_helper(|f, g| { let _foo: Self::Kind<'_> = f([]); g(&_foo); }); } } }; ( impl[$($params:tt)+] Opaque for $key:ty { type Kind<$l:lifetime> = $kind:ty; } $(where $($bounds:tt)*)? ) => { unsafe impl<$($params)+> $crate::Opaque for $key $(where $($bounds)*)? { type Kind<$l> = $kind where Self: $l; fn ub_check() { fn ub_detect_helper<$($params)+>( _f: impl ::core::ops::Fn( for<$l> fn([&$l (); 0]) -> $kind, for<$l> fn(&$l $kind) ) ) $(where $($bounds)*)? { } ub_detect_helper(|f, g| { let _foo: Self::Kind<'_> = f([]); g(&_foo); }); } } }; } /// Holds an "opaqueified" `T::Kind`. /// /// Note the lifetime, `'k`. This can be anything, as long as `T` outlives it. /// /// # Examples /// /// ```rust /// #![feature(generic_associated_types)] /// /// use core::cell::Cell; /// /// use selfref::Holder; /// use selfref::SelfRef; /// use selfref::new_with_closure; /// use selfref::opaque; /// /// #[derive(Default)] /// struct Foo<'a> { /// foo: Cell>>, /// } /// impl<'a> SelfRef<'a> for Foo<'a> {} /// /// struct FooKey; /// opaque! { /// impl Opaque for FooKey { /// type Kind<'a> = Foo<'a>; /// } /// } /// /// fn main() { /// // We can use a closure here, but we need to give the compiler a hint. /// let holder = Holder::<'_, FooKey>::new_with( /// new_with_closure::(|foo| Foo::default()) /// ); /// } /// ``` pub struct Holder<'k, T> where T: Opaque + 'k { inner: ::Kind<'k>, _pinned: PhantomPinned, } /// Helper trait for creating a [`Holder`]. /// /// This is necessary because closures don't work properly here. /// /// See [`Holder::new_with`] for examples. pub trait NewWith<'k, T: Opaque + 'k> { /// Creates a new `T::Kind` with an unbound lifetime. fn new_with<'a>(self) -> T::Kind<'a> where 'k: 'a; } impl<'k, T: Opaque + 'k, F> NewWith<'k, T> for F where F: for<'a> FnOnce([&'a (); 0]) -> ::Kind<'a> { fn new_with<'a>(self) -> T::Kind<'a> where 'k: 'a { self([]) } } /// Helper for creating a [`Holder`] using a closure. /// /// This only works if `K` is `'static`. pub fn new_with_closure(f: F) -> F where F: for<'a> FnOnce([&'a (); 0]) -> ::Kind<'a> { f } impl<'k, T> Holder<'k, T> where T: Opaque { /// Creates a new holder. /// /// # Examples /// /// Simple example: /// /// ```rust /// #![feature(generic_associated_types)] /// /// use core::cell::Cell; /// /// use selfref::Holder; /// use selfref::SelfRef; /// use selfref::new_with_closure; /// use selfref::opaque; /// /// #[derive(Default)] /// struct Foo<'a> { /// foo: Cell>>, /// } /// impl<'a> SelfRef<'a> for Foo<'a> {} /// /// struct FooKey; /// opaque! { /// impl Opaque for FooKey { /// type Kind<'a> = Foo<'a>; /// } /// } /// /// fn main() { /// // We can use a closure here, but we need to help the compiler. /// let holder = Holder::<'_, FooKey>::new_with( /// new_with_closure::(|foo| Foo::default()) /// ); /// } /// ``` /// /// Lifetime parameters: /// /// ```rust /// #![feature(generic_associated_types)] /// /// use core::cell::Cell; /// use core::marker::PhantomData; /// /// use selfref::Holder; /// use selfref::NewWith; /// use selfref::SelfRef; /// use selfref::opaque; /// /// struct Foo<'a, 'b: 'a> { /// foo: Cell>>, /// t: &'b str, /// } /// impl<'a, 'b> SelfRef<'a> for Foo<'a, 'b> {} /// /// struct FooKey<'b>(PhantomData<&'b str>); /// opaque! { /// impl['b] Opaque for FooKey<'b> { /// type Kind<'a> = Foo<'a, 'b>; /// } /// } /// /// fn main() { /// 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 { /// Foo { /// foo: Default::default(), /// t: self.0, /// } /// } /// } /// let stack_array: [u8; 5] = *b"hello"; /// // a non-'static &str /// let stack_str = core::str::from_utf8(&stack_array).unwrap(); /// let holder = Holder::new_with(FooBuilder(stack_str)); /// } /// ``` pub fn new_with(f: F) -> Self where F: NewWith<'k, T> { Self { // it is important that the constructor cannot observe 'k! inner: f.new_with(), _pinned: PhantomPinned } } } /// Helper trait for working with a [`Holder`]. /// /// This is necessary because closures don't work properly here. /// /// See [`Holder::operate_in`] for examples. pub trait OperateIn<'k, T: Opaque + 'k> { /// The value returned by this operation. type Out; /// Do this operation. fn operate_in<'a>(self, x: Pin<&'a T::Kind<'a>>) -> Self::Out where 'k: 'a; } impl<'k, T: Opaque + 'k, F, R> OperateIn<'k, T> for F where F: for<'a> FnOnce(Pin<&'a T::Kind<'a>>) -> R { type Out = R; fn operate_in<'a>(self, x: Pin<&'a T::Kind<'a>>) -> R where 'k: 'a { self(x) } } /// Helper for working with a [`Holder`] using a closure. /// /// This only works if `K` is `'static`. pub fn operate_in_closure(f: F) -> F where F: for<'a> FnOnce(Pin<&'a ::Kind<'a>>) -> R { f } impl<'k, T> Holder<'k, T> where T: Opaque { /// Operates in this (pinned) holder. /// /// This "unwraps" the value in this holder, and binds its lifetime to a /// new stack frame. /// /// # Examples /// /// Simple example: /// /// ```rust /// #![feature(generic_associated_types)] /// #![feature(pin_macro)] /// /// use core::cell::Cell; /// use core::pin::pin; /// /// use selfref::Holder; /// use selfref::SelfRef; /// use selfref::new_with_closure; /// use selfref::opaque; /// use selfref::operate_in_closure; /// /// #[derive(Default)] /// struct Foo<'a> { /// foo: Cell>>, /// } /// impl<'a> SelfRef<'a> for Foo<'a> {} /// /// struct FooKey; /// opaque! { /// impl Opaque for FooKey { /// type Kind<'a> = Foo<'a>; /// } /// } /// /// fn main() { /// let holder = pin!(Holder::<'_, FooKey>::new_with( /// new_with_closure::(|foo| Foo::default()) /// )); /// // Actually making our Foo refer to itself. /// holder.as_ref().operate_in( /// operate_in_closure::(|foo| { /// foo.foo.set(Some(foo.get_ref())); /// }) /// ); /// } /// ``` /// /// With lifetime parameters: /// /// ```rust /// #![feature(generic_associated_types)] /// #![feature(pin_macro)] /// /// use core::cell::Cell; /// use core::marker::PhantomData; /// use core::pin::Pin; /// use core::pin::pin; /// /// use selfref::Holder; /// use selfref::NewWith; /// use selfref::OperateIn; /// use selfref::SelfRef; /// use selfref::opaque; /// /// struct Foo<'a, 'b: 'a> { /// foo: Cell>>, /// t: &'b str, /// } /// impl<'a, 'b> SelfRef<'a> for Foo<'a, 'b> {} /// /// struct FooKey<'b>(PhantomData<&'b str>); /// opaque! { /// impl['b] Opaque for FooKey<'b> { /// type Kind<'a> = Foo<'a, 'b>; /// } /// } /// /// fn main() { /// 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 { /// Foo { /// foo: Default::default(), /// t: self.0, /// } /// } /// } /// let stack_array: [u8; 5] = *b"hello"; /// // a non-'static &str /// let stack_str = core::str::from_utf8(&stack_array).unwrap(); /// let holder = pin!(Holder::new_with(FooBuilder(stack_str))); /// // Actually making our Foo refer to itself. /// struct SetFooRef; /// impl<'k, 'b: 'k> OperateIn<'k, FooKey<'b>> for SetFooRef { /// type Out = (); /// fn operate_in<'a>(self, foo: Pin<&'a Foo<'a, 'b>>) /// where 'k: 'a { /// foo.foo.set(Some(foo.get_ref())); /// } /// } /// holder.as_ref().operate_in(SetFooRef); /// } /// ``` pub fn operate_in<'i, F, R>(self: Pin<&'i Self>, f: F) -> R where F: OperateIn<'k, T, Out=R> { /// Converts Pin<&'a T::Kind<'k>> to Pin<&'b T::Kind<'b>> unsafe fn upcast_dangling<'a, 'b, 'c, T: Opaque + 'c>(x: Pin<&'a T::Kind<'c>>) -> Pin<&'b T::Kind<'b>> where T::Kind<'c>: 'a { mem::transmute(x) } f.operate_in(unsafe { upcast_dangling::<'i, 'k, '_, T> (self.map_unchecked(|self_ref| { &self_ref.inner })) }) } }