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}