selfref/
lib.rs

1// SelfRef - Pain-free self-referential pinned types
2// Copyright (C) 2022 Soni L.
3// This software is made with love by a queer trans person.
4// With help from quinedot
5//
6// SPDX-License-Identifier: MIT OR Apache-2.0
7
8#![no_std]
9#![cfg_attr(feature="nightly", feature(dropck_eyepatch))]
10
11//! An experimental approach to self-referential structs in Rust.
12//!
13//! This crate provides an alternative approach to self-referential structs,
14//! where instead of providing you with a macro or framework where you define
15//! a self-referential struct and it handles all of the details for you, we try
16//! to expose the abstractions and building blocks for making self-referential
17//! structs work well in safe Rust.
18//!
19//! For example, a [`Holder`] is a safe wrapper around a self-referential
20//! struct, providing safe APIs for constructing and manipulating a
21//! self-referential struct. However, and unlike other self-referential crates,
22//! it does not dictate the backing storage of the struct. The [`Opaque`] trait
23//! is used to identify a self-referential struct for use with a [`Holder`] -
24//! since Rust does not support higher kinded types (HKTs), this crate uses
25//! generic associated types (GATs) as a workaround.
26//!
27//! To use the crate, first define a self-referential struct in plain Rust:
28//!
29//! ```rust
30//! use std::cell::Cell;
31//!
32//! // Your self-referential struct.
33//! struct MySelfRefStruct<'this> {
34//!     // Rust uses RAII-like struct construction, as a result this must be
35//!     // somehow initialized after the struct. We can use an Option in a Cell
36//!     // for this.
37//!     this: Cell<Option<&'this MySelfRefStruct<'this>>>,
38//! }
39//! ```
40//!
41//! Then, define a type to implement the `Opaque`. This can be done
42//! automatically with the `opaque` macro:
43//!
44//! ```rust
45//! # use std::cell::Cell;
46//! # // Your self-referential struct.
47//! # struct MySelfRefStruct<'this> {
48//! #     // Rust uses RAII-like struct construction, as a result this must be
49//! #     // somehow initialized after the struct. We can use an Option in a Cell
50//! #     // for this.
51//! #     this: Cell<Option<&'this MySelfRefStruct<'this>>>,
52//! # }
53//!
54//! use selfref::opaque;
55//!
56//! // A "marker type" that implements `Opaque`.
57//! // This follows the "type family" GAT pattern.
58//! struct MySelfRefStructKey;
59//!
60//! opaque! {
61//!     impl Opaque for MySelfRefStructKey {
62//!         type Kind<'this> = MySelfRefStruct<'this>;
63//!     }
64//! }
65//!
66//! // Alternatively, it is possible to implement `Opaque` on, for example,
67//! // `MySelfRefStruct<'static>`, but the added lifetime adds verbosity which
68//! // may be considered unnecessary/undesired.
69//! ```
70//!
71//! Now you can construct a `Holder` and pick a storage for it. For example,
72//! in a `Box`:
73//!
74//! ```rust
75//! # use std::cell::Cell;
76//! # // Your self-referential struct.
77//! # struct MySelfRefStruct<'this> {
78//! #     // Rust uses RAII-like struct construction, as a result this must be
79//! #     // somehow initialized after the struct. We can use an Option in a Cell
80//! #     // for this.
81//! #     this: Cell<Option<&'this MySelfRefStruct<'this>>>,
82//! # }
83//! # use selfref::opaque;
84//! # // A "marker type" that implements `Opaque`.
85//! # // This follows the "type family" GAT pattern.
86//! # struct MySelfRefStructKey;
87//! # opaque! {
88//! #     impl Opaque for MySelfRefStructKey {
89//! #         type Kind<'this> = MySelfRefStruct<'this>;
90//! #     }
91//! # }
92//! # // Alternatively, it is possible to implement `Opaque` on, for example,
93//! # // `MySelfRefStruct<'static>`, but the added lifetime adds verbosity which
94//! # // may be considered unnecessary/undesired.
95//!
96//! use selfref::Holder;
97//!
98//! fn main() {
99//!     // first, construct the struct
100//!     let holder = Box::pin(Holder::<'_, MySelfRefStructKey>::new_with(
101//!         |foo| foo.build({
102//!             MySelfRefStruct {
103//!                 this: Cell::new(None)
104//!             }
105//!         })
106//!     ));
107//!
108//!     // then, build the self-reference
109//!     holder.as_ref().operate_in(
110//!         |this| {
111//!             this.this.set(Some(this.get_ref()));
112//!         }
113//!     );
114//! }
115//! ```
116//!
117//! # Examples
118//!
119//! This is a more complex example borrowing from an external lifetime:
120//!
121//! ```rust
122//! use core::cell::Cell;
123//! use core::marker::PhantomData;
124//! use core::pin::Pin;
125//! 
126//! use selfref::Holder;
127//! use selfref::opaque;
128//!
129//! struct Foo<'a, 'b: 'a> {
130//!     foo: Cell<Option<&'a Foo<'a, 'b>>>,
131//!     t: &'b str,
132//! }
133//!
134//! struct FooKey<'b>(PhantomData<&'b str>);
135//! opaque! {
136//!     impl['b] Opaque for FooKey<'b> {
137//!         type Kind<'a> = Foo<'a, 'b>;
138//!     }
139//! }
140//!
141//! fn main() {
142//!     // a non-'static &str
143//!     let stack_array: [u8; 5] = *b"hello";
144//!     let stack_str = core::str::from_utf8(&stack_array).unwrap();
145//!
146//!     // construct the struct
147//!     let holder = Box::pin(Holder::<'_, FooKey<'_>>::new_with(|foo| {
148//!         foo.build(Foo {
149//!             foo: Default::default(),
150//!             t: stack_str,
151//!         })
152//!     }));
153//!
154//!     holder.as_ref().operate_in(|foo| {
155//!         foo.foo.set(Some(foo.get_ref()));
156//!     });
157//! }
158//! ```
159//!
160//! # Features
161//!
162//! Due to [PhantomData is unsound](https://github.com/rust-lang/rust/issues/102810)
163//! we currently require the following features for `T: ?Sized` support in
164//! `selfref::opaque!`:
165//!
166//! - `alloc` - `selfref::opaque!` for `T: ?Sized` is provided by `Box`.
167//! - `nightly` - `selfref::opaque!` for `T: ?Sized` is provided by a *wrapper*
168//!     around `PhantomData`, which works around the above issue. we call this
169//!     "PhantomDrop".
170//!
171//! When enabling both features, `nightly` takes over and we use the wrapper
172//! always. This doesn't make a significant difference since the generated UB
173//! check is dead code anyway, but `PhantomDrop` doesn't depend on `alloc` and
174//! can be used in `no_std` environments.
175//!
176//! If not using either feature, `T: ?Sized` support requires `unsafe`ly
177//! implementing `Opaque`.
178//!
179//! Note that we do **not** enable any features by default! We assume most
180//! folks aren't coming to this crate for its `T: ?Sized` support, so these are
181//! the best defaults for crates to depend on. If they do need the `?Sized`
182//! support they can just enable one of these (probably `alloc`).
183
184use core::marker::PhantomPinned;
185use core::pin::Pin;
186use core::mem;
187
188// there's no sound way to dropck T: ?Sized without either alloc or nightly.
189//
190// so we just have the user opt-in to alloc or nightly as desired.
191//
192// when using alloc, we use Box<T> for UBCheck.
193//
194// when using nightly, we use our custom PhantomDrop<T> for UBCheck.
195//
196// when using neither, we just error on T: ?Sized and require a manual unsafe
197// impl of Opaque.
198
199#[cfg(all(feature="alloc", not(feature="nightly")))]
200extern crate alloc;
201
202#[cfg(all(feature="alloc", not(feature="nightly")))]
203#[doc(hidden)]
204pub struct UBCheck<T: ?Sized>(alloc::boxed::Box<T>);
205
206#[cfg(feature="nightly")]
207#[doc(hidden)]
208pub struct UBCheck<T: ?Sized>(core::marker::PhantomData<T>);
209
210#[cfg(all(not(feature="alloc"), not(feature="nightly")))]
211#[doc(hidden)]
212pub struct UBCheck<T>(T); // use feature "alloc" or "nightly" for T: ?Sized
213
214#[cfg(feature="nightly")]
215// SAFETY: dropck's like a Box<T>, but is no-alloc friendly.
216unsafe impl<#[may_dangle] T: ?Sized> Drop for UBCheck<T> {
217    fn drop(&mut self) {}
218}
219
220#[cfg(feature="qcell")]
221pub mod srce;
222
223/// An opaqueified self-referential struct "key".
224///
225/// # Safety
226///
227/// This is unsafe because there are a bunch of soundness invariants that need
228/// to be upheld. The following list is non-exhaustive:
229///
230/// - `Kind` must not have a `Drop` impl in any "path" that may trace back to
231///     the original self-referential type, if said `Drop` impl can observe
232///     the self-referential type.
233/// - We assume `Kind` has the same layout for any `'a`. This is true as of the
234///     time of writing this, and relies on Rust not having lifetime
235///     specialization.
236///
237/// It's recommended to use the `selfref::opaque!` macro instead, which
238/// enforces these invariants. For example, this doesn't compile:
239///
240/// ```rust compile_fail
241/// use std::cell::Cell;
242/// use selfref::opaque;
243///
244/// struct Foo<'a> {
245///     foo: Cell<Option<&'a Foo<'a>>>,
246/// }
247///
248/// impl<'a> Drop for Foo<'a> {
249///     fn drop(&mut self) {
250///     }
251/// }
252///
253/// struct FooKey;
254/// opaque! {
255///     impl Opaque for FooKey {
256///         type Kind<'a> = Foo<'a>;
257///     }
258/// }
259/// ```
260///
261/// But by removing the `Drop` impl, it compiles:
262///
263/// ```rust
264/// use std::cell::Cell;
265/// use selfref::opaque;
266///
267/// struct Foo<'a> {
268///     foo: Cell<Option<&'a Foo<'a>>>,
269/// }
270///
271/// //impl<'a> Drop for Foo<'a> {
272/// //    fn drop(&mut self) {
273/// //    }
274/// //}
275///
276/// struct FooKey;
277/// opaque! {
278///     impl Opaque for FooKey {
279///         type Kind<'a> = Foo<'a>;
280///     }
281/// }
282/// ```
283///
284/// # Examples
285///
286/// ```rust
287/// use core::cell::Cell;
288/// 
289/// use selfref::Opaque;
290///
291/// struct Foo<'a> {
292///     foo: Cell<Option<&'a Foo<'a>>>,
293/// }
294///
295/// struct FooKey;
296/// // SAFETY: Foo has no Drop impl and has the same layout for any 'a.
297/// unsafe impl Opaque for FooKey {
298///     type Kind<'a> = Foo<'a>;
299/// }
300/// ```
301pub unsafe trait Opaque {
302    /// The actual self-referential struct.
303    type Kind<'a>: ?Sized where Self: 'a;
304    #[doc(hidden)]
305    fn ub_check() {
306    }
307}
308
309/// Creates an opaqueified self-referential struct "key".
310///
311/// Safe wrapper around [`Opaque`] that checks the soundness requirements at
312/// compile-time.
313///
314/// There are 2 forms of this macro. The second form accepts type parameters.
315///
316/// Note that where bounds go after the impl block.
317///
318/// # Examples
319///
320/// Simple example:
321///
322/// ```rust
323/// use core::cell::Cell;
324/// 
325/// use selfref::opaque;
326///
327/// struct Foo<'a> {
328///     foo: Cell<Option<&'a Foo<'a>>>,
329/// }
330///
331/// struct FooKey;
332/// opaque! {
333///     impl Opaque for FooKey {
334///         type Kind<'a> = Foo<'a>;
335///     }
336/// }
337/// ```
338///
339/// Type parameters and where bounds:
340///
341/// ```rust
342/// use core::cell::Cell;
343/// use core::fmt::Display;
344/// use core::marker::PhantomData;
345/// 
346/// use selfref::opaque;
347///
348/// struct Foo<'a, T: Display> {
349///     foo: Cell<Option<&'a Foo<'a, T>>>,
350///     t: T,
351/// }
352///
353/// struct FooKey<T>(PhantomData<T>);
354/// opaque! {
355///     impl[T] Opaque for FooKey<T> {
356///         type Kind<'a> = Foo<'a, T>;
357///     } where T: Display
358/// }
359/// ```
360#[macro_export]
361macro_rules! opaque {
362    (
363        impl Opaque for $key:ty {
364            type Kind<$l:lifetime> = $kind:ty;
365        } $(where $($bounds:tt)*)?
366    ) => {
367        unsafe impl $crate::Opaque for $key $(where $($bounds)*)? {
368            type Kind<$l> = $kind where Self: $l;
369            fn ub_check() {
370                fn ub_detect_helper(
371                    _f: impl ::core::ops::Fn(
372                        for<$l> fn([&$l (); 0]) -> $crate::UBCheck<$kind>,
373                        for<$l> fn(&$l $crate::UBCheck<$kind>)
374                    )
375                ) $(where $($bounds)*)? {
376                }
377                ub_detect_helper(|f, g| {
378                    let x: $crate::UBCheck<Self::Kind<'_>> = f([]);
379                    g(&x);
380                });
381            }
382        }
383    };
384    (
385        impl[$($params:tt)+] Opaque for $key:ty {
386            type Kind<$l:lifetime> = $kind:ty;
387        } $(where $($bounds:tt)*)?
388    ) => {
389        unsafe impl<$($params)+> $crate::Opaque for $key
390        $(where $($bounds)*)? {
391            type Kind<$l> = $kind where Self: $l;
392            fn ub_check() {
393                fn ub_detect_helper<$($params)+>(
394                    _f: impl ::core::ops::Fn(
395                        for<$l> fn([&$l (); 0]) -> $crate::UBCheck<$kind>,
396                        for<$l> fn(&$l $crate::UBCheck<$kind>)
397                    )
398                ) $(where $($bounds)*)? {
399                }
400                ub_detect_helper(|f, g| {
401                    let x: $crate::UBCheck<Self::Kind<'_>> = f([]);
402                    g(&x);
403                });
404            }
405        }
406    };
407}
408
409/// Holds an "opaqueified" `T::Kind`.
410///
411/// Note the lifetime, `'k`. This can be anything, as long as `T` outlives it.
412/// 
413/// # Examples
414///
415/// ```rust
416/// use core::cell::Cell;
417/// 
418/// use selfref::Holder;
419/// use selfref::opaque;
420///
421/// #[derive(Default)]
422/// struct Foo<'a> {
423///     foo: Cell<Option<&'a Foo<'a>>>,
424/// }
425///
426/// struct FooKey;
427/// opaque! {
428///     impl Opaque for FooKey {
429///         type Kind<'a> = Foo<'a>;
430///     }
431/// }
432///
433/// fn main() {
434///     // We can use a closure here, but we need to give the compiler a hint.
435///     let holder = Holder::<'_, FooKey>::new_with(
436///         |foo| foo.build(Foo::default())
437///     );
438/// }
439/// ```
440pub struct Holder<'k, T> where T: Opaque + 'k {
441  _pinned: PhantomPinned,
442  inner: <T as Opaque>::Kind<'k>,
443}
444
445/// Helper for creating a [`Holder`].
446///
447/// This is necessary because closures don't work properly here.
448///
449/// See [`Holder::new_with`] for examples.
450pub struct Builder<'k, T: Opaque + 'k> where T::Kind<'k>: Sized {
451    inner: Option<T::Kind<'k>>,
452}
453
454impl<'k, T: Opaque + 'k> Builder<'k, T> where T::Kind<'k>: Sized {
455    /// Builds the [`Holder`].
456    #[inline]
457    pub fn build(&mut self, t: T::Kind<'k>) {
458        self.inner = Some(t);
459    }
460}
461
462impl<'k, T> Holder<'k, T> where T: Opaque {
463    /// Creates a new holder.
464    ///
465    /// # Examples
466    ///
467    /// Simple example:
468    ///
469    /// ```rust
470    /// use core::cell::Cell;
471    /// 
472    /// use selfref::Holder;
473    /// use selfref::opaque;
474    ///
475    /// #[derive(Default)]
476    /// struct Foo<'a> {
477    ///     foo: Cell<Option<&'a Foo<'a>>>,
478    /// }
479    ///
480    /// struct FooKey;
481    /// opaque! {
482    ///     impl Opaque for FooKey {
483    ///         type Kind<'a> = Foo<'a>;
484    ///     }
485    /// }
486    ///
487    /// fn main() {
488    ///     // We can use a closure here, but we need to help the compiler.
489    ///     let holder = Holder::<'_, FooKey>::new_with(
490    ///         |foo| foo.build(Foo::default())
491    ///     );
492    /// }
493    /// ```
494    ///
495    /// Lifetime parameters:
496    ///
497    /// ```rust
498    /// use core::cell::Cell;
499    /// use core::marker::PhantomData;
500    /// 
501    /// use selfref::Holder;
502    /// use selfref::opaque;
503    ///
504    /// struct Foo<'a, 'b: 'a> {
505    ///     foo: Cell<Option<&'a Foo<'a, 'b>>>,
506    ///     t: &'b str,
507    /// }
508    ///
509    /// struct FooKey<'b>(PhantomData<&'b str>);
510    /// opaque! {
511    ///     impl['b] Opaque for FooKey<'b> {
512    ///         type Kind<'a> = Foo<'a, 'b>;
513    ///     }
514    /// }
515    ///
516    /// fn main() {
517    ///     let stack_array: [u8; 5] = *b"hello";
518    ///     // a non-'static &str
519    ///     let stack_str = core::str::from_utf8(&stack_array).unwrap();
520    ///     let holder = Holder::<'_, FooKey<'_>>::new_with(|foo| {
521    ///         foo.build(Foo {
522    ///             foo: Default::default(),
523    ///             t: stack_str,
524    ///         });
525    ///     });
526    /// }
527    /// ```
528    pub fn new_with<F>(f: F) -> Self
529    where
530        F: for<'a> FnOnce(&mut Builder<'a, T>),
531        T::Kind<'k>: Sized,
532    {
533        let mut builder = Builder { inner: None };
534        f(&mut builder);
535        Self {
536            // it is important that the constructor cannot observe 'k!
537            inner: builder.inner.unwrap(),
538            _pinned: PhantomPinned
539        }
540    }
541}
542
543/// Wrapper around a `Pin<&'k T::Kind<'k>>` for implied bounds.
544///
545/// Derefs to `Pin<&'k T::Kind<'k>>`.
546pub struct OperateIn<'k, T> where T: Opaque + 'k {
547    inner: Pin<&'k T::Kind<'k>>,
548}
549
550impl<'k, T> core::ops::Deref for OperateIn<'k, T> where T: Opaque {
551    type Target = Pin<&'k T::Kind<'k>>;
552
553    fn deref(&self) -> &Pin<&'k T::Kind<'k>> {
554        &self.inner
555    }
556}
557
558impl<'k, T> Holder<'k, T> where T: Opaque {
559    /// Operates in this (pinned) holder.
560    ///
561    /// This "unwraps" the value in this holder, and binds its lifetime to a
562    /// new stack frame.
563    ///
564    /// # Examples
565    ///
566    /// Simple example:
567    ///
568    /// ```rust
569    /// use core::cell::Cell;
570    /// 
571    /// use selfref::Holder;
572    /// use selfref::opaque;
573    ///
574    /// #[derive(Default)]
575    /// struct Foo<'a> {
576    ///     foo: Cell<Option<&'a Foo<'a>>>,
577    /// }
578    ///
579    /// struct FooKey;
580    /// opaque! {
581    ///     impl Opaque for FooKey {
582    ///         type Kind<'a> = Foo<'a>;
583    ///     }
584    /// }
585    ///
586    /// fn main() {
587    ///     let holder = Box::pin(Holder::<'_, FooKey>::new_with(
588    ///         |foo| foo.build(Foo::default())
589    ///     ));
590    ///     // Actually making our Foo refer to itself.
591    ///     holder.as_ref().operate_in(
592    ///         |foo| {
593    ///             foo.foo.set(Some(foo.get_ref()));
594    ///         }
595    ///     );
596    /// }
597    /// ```
598    ///
599    /// With lifetime parameters:
600    ///
601    /// ```rust
602    /// use core::cell::Cell;
603    /// use core::marker::PhantomData;
604    /// use core::pin::Pin;
605    /// 
606    /// use selfref::Holder;
607    /// use selfref::opaque;
608    ///
609    /// struct Foo<'a, 'b: 'a> {
610    ///     foo: Cell<Option<&'a Foo<'a, 'b>>>,
611    ///     t: &'b str,
612    /// }
613    ///
614    /// struct FooKey<'b>(PhantomData<&'b str>);
615    /// opaque! {
616    ///     impl['b] Opaque for FooKey<'b> {
617    ///         type Kind<'a> = Foo<'a, 'b>;
618    ///     }
619    /// }
620    ///
621    /// fn main() {
622    ///     let stack_array: [u8; 5] = *b"hello";
623    ///     // a non-'static &str
624    ///     let stack_str = core::str::from_utf8(&stack_array).unwrap();
625    ///     let holder = Box::pin(Holder::<'_, FooKey<'_>>::new_with(|foo| {
626    ///         foo.build(Foo {
627    ///             foo: Default::default(),
628    ///             t: stack_str,
629    ///         });
630    ///     }));
631    ///     // Actually making our Foo refer to itself.
632    ///     holder.as_ref().operate_in(|foo| {
633    ///         foo.foo.set(Some(foo.get_ref()));
634    ///     });
635    /// }
636    /// ```
637    pub fn operate_in<'i, F, R>(self: Pin<&'i Self>, f: F) -> R
638    where 
639        F: for<'x> FnOnce(OperateIn<'x, T>) -> R
640    {
641        /// Converts `Pin<&'a T::Kind<'k>>` to `Pin<&'b T::Kind<'b>>`.
642        ///
643        /// Not sure why this is called "upcast_dangling" since none of these
644        /// are actually dangling. But anyway.
645        unsafe fn upcast_dangling<'a, 'b, 'c, T: Opaque + 'c>(
646            x: Pin<&'a T::Kind<'c>>,
647        ) -> Pin<&'b T::Kind<'b>>
648        where T::Kind<'c>: 'a {
649            mem::transmute(x)
650        }
651        f(OperateIn {
652            inner: unsafe {
653                upcast_dangling::<'i, 'k, '_, T>
654                (self.map_unchecked(|self_ref| {
655                    &self_ref.inner
656                }))
657            }
658        })
659    }
660}