Skip to main content

potential_well/
traits.rs

1//! [`Well`] and [`WellMut`] traits.
2use core::{
3    ops::{Deref, DerefMut},
4    pin::Pin,
5    ptr::NonNull,
6};
7
8#[cfg(feature = "alloc")]
9use {
10    crate::atomic::{PotentialAtomic, PotentialAtomicOption},
11    alloc::{boxed::Box, rc::Rc, sync::Arc},
12};
13
14/// Place that can store a smart pointer.
15///
16/// # Safety
17///
18/// Types that implement this trait assert that:
19///
20/// 1. The `insert` and `remove` methods are true inverses of each other with no side effects.
21/// 2. The pointer to the data is stable on [`Deref`] and [`DerefMut`] (if implemented), *and* this
22///    pointer is the same as the one that is returned by [`remove`].
23/// 3. The data may be read even when outside the well.
24/// 4. If [`DerefMut`] is implemented, the data may be mutated even when outside the well.
25///
26/// [`insert`]: Well::insert
27/// [`remove`]: Well::remove
28pub unsafe trait Well: Deref<Target: Sized> {
29    /// Put the data back into the well.
30    ///
31    /// # Safety
32    ///
33    /// The pointer passed to [`insert`] must previously have been received from [`remove`].
34    ///
35    /// [`insert`]: Well::insert
36    /// [`remove`]: Well::remove
37    unsafe fn insert(ptr: NonNull<Self::Target>) -> Self;
38
39    /// Take the data out of the well.
40    fn remove(self) -> NonNull<Self::Target>;
41}
42
43/// Implementation of trait alias that uses trait aliases.
44#[cfg(feature = "nightly")]
45macro_rules! trait_alias {
46    (
47        $(#[$attr:meta])*
48        $vis:vis trait $t:ident = ($($bound:tt)*);
49    ) => {
50        $(#[$attr])*
51        ///
52        /// Implemented as a trait alias with the `nightly` feature,
53        /// and an automatically-implemented trait otherwise.
54        $vis trait $t = $($bound)*;
55    }
56}
57
58/// Implementation of trait alias that uses traits.
59#[cfg(not(feature = "nightly"))]
60macro_rules! trait_alias {
61    (
62        $(#[$attr:meta])*
63        $vis:vis trait $t:ident = ($($bound:tt)*);
64    ) => {
65        $(#[$attr])*
66        ///
67        /// Implemented as a trait alias with the `nightly` feature,
68        /// and an automatically-implemented trait otherwise.
69        $vis trait $t: $($bound)* {}
70        impl<T: $($bound)*> $t for T {}
71    }
72}
73
74trait_alias! {
75    /// Alias for <code>[Well] + [DerefMut]</code>.
76    pub trait WellMut = (DerefMut + Well);
77}
78
79// SAFETY: A pointer in its almost-rawest form.
80unsafe impl<T> Well for &T {
81    #[inline]
82    unsafe fn insert(ptr: NonNull<T>) -> Self {
83        // SAFETY: Ensured by caller.
84        unsafe { ptr.as_ref() }
85    }
86
87    #[inline]
88    fn remove(self) -> NonNull<T> {
89        NonNull::from(self)
90    }
91}
92
93// SAFETY: A pointer in its almost-rawest form.
94unsafe impl<T> Well for Pin<&T> {
95    #[inline]
96    unsafe fn insert(ptr: NonNull<T>) -> Self {
97        // SAFETY: Ensured by caller.
98        unsafe { Pin::new_unchecked(ptr.as_ref()) }
99    }
100
101    #[inline]
102    fn remove(self) -> NonNull<T> {
103        NonNull::from(self.get_ref())
104    }
105}
106
107// SAFETY: A pointer in its almost-rawest form.
108unsafe impl<T> Well for &mut T {
109    #[inline]
110    unsafe fn insert(mut ptr: NonNull<T>) -> Self {
111        // SAFETY: Ensured by caller.
112        unsafe { ptr.as_mut() }
113    }
114
115    #[inline]
116    fn remove(self) -> NonNull<T> {
117        NonNull::from(self)
118    }
119}
120
121// SAFETY: A pointer in its almost-rawest form.
122unsafe impl<T> Well for Pin<&mut T> {
123    #[inline]
124    unsafe fn insert(mut ptr: NonNull<T>) -> Self {
125        // SAFETY: Ensured by caller.
126        unsafe { Pin::new_unchecked(ptr.as_mut()) }
127    }
128
129    #[inline]
130    fn remove(self) -> NonNull<T> {
131        // SAFETY: We can only get a pinned version back out of the well.
132        unsafe { NonNull::from(self.get_unchecked_mut()) }
133    }
134}
135
136#[cfg(any(test, feature = "alloc"))]
137// SAFETY: `Box` just wraps a pointer.
138unsafe impl<T> Well for Box<T> {
139    #[inline]
140    unsafe fn insert(ptr: NonNull<T>) -> Self {
141        // SAFETY: Ensured by caller.
142        unsafe { Box::from_raw(ptr.as_ptr()) }
143    }
144
145    #[inline]
146    fn remove(self) -> NonNull<T> {
147        // SAFETY: Box's pointer is always non-null.
148        unsafe { NonNull::new_unchecked(Box::into_raw(self)) }
149    }
150}
151
152#[cfg(any(test, feature = "alloc"))]
153// SAFETY: If we keep the pin, everything works out.
154unsafe impl<T> Well for Pin<Box<T>> {
155    #[inline]
156    unsafe fn insert(ptr: NonNull<T>) -> Self {
157        // SAFETY: Ensured by caller.
158        unsafe { Pin::new_unchecked(Box::from_raw(ptr.as_ptr())) }
159    }
160
161    #[inline]
162    fn remove(self) -> NonNull<T> {
163        // SAFETY: Box's pointer is always non-null, and we're not moving anything out of the box.
164        unsafe { NonNull::new_unchecked(Box::into_raw(Pin::into_inner_unchecked(self))) }
165    }
166}
167
168#[cfg(feature = "alloc")]
169// SAFETY: `Rc` accounts for the reference-counter offsets in `into_raw` and `from_raw`.
170unsafe impl<T> Well for Rc<T> {
171    #[inline]
172    unsafe fn insert(ptr: NonNull<T>) -> Self {
173        // SAFETY: Ensured by caller.
174        unsafe { Rc::from_raw(ptr.as_ptr()) }
175    }
176
177    #[inline]
178    fn remove(self) -> NonNull<T> {
179        // SAFETY: Rc's pointer is always non-null.
180        unsafe { NonNull::new_unchecked(Rc::into_raw(self).cast_mut()) }
181    }
182}
183
184#[cfg(feature = "alloc")]
185// SAFETY: If we keep the pin, everything works out.
186unsafe impl<T> Well for Pin<Rc<T>> {
187    #[inline]
188    unsafe fn insert(ptr: NonNull<T>) -> Self {
189        // SAFETY: Ensured by caller.
190        unsafe { Pin::new_unchecked(Rc::from_raw(ptr.as_ptr())) }
191    }
192
193    #[inline]
194    fn remove(self) -> NonNull<T> {
195        // SAFETY: Rc's pointer is always non-null, and we're not moving anything out of the `Rc`.
196        unsafe { NonNull::new_unchecked(Rc::into_raw(Pin::into_inner_unchecked(self)).cast_mut()) }
197    }
198}
199
200#[cfg(feature = "alloc")]
201// SAFETY: `Arc` accounts for the reference-counter offsets in `into_raw` and `from_raw`.
202unsafe impl<T> Well for Arc<T> {
203    #[inline]
204    unsafe fn insert(ptr: NonNull<T>) -> Self {
205        // SAFETY: Ensured by caller.
206        unsafe { Arc::from_raw(ptr.as_ptr()) }
207    }
208
209    #[inline]
210    fn remove(self) -> NonNull<T> {
211        // SAFETY: Arc's pointer is always non-null.
212        unsafe { NonNull::new_unchecked(Arc::into_raw(self).cast_mut()) }
213    }
214}
215
216#[cfg(feature = "alloc")]
217// SAFETY: If we keep the pin, everything works out.
218unsafe impl<T> Well for Pin<Arc<T>> {
219    #[inline]
220    unsafe fn insert(ptr: NonNull<T>) -> Self {
221        // SAFETY: Ensured by caller.
222        unsafe { Pin::new_unchecked(Arc::from_raw(ptr.as_ptr())) }
223    }
224
225    #[inline]
226    fn remove(self) -> NonNull<T> {
227        // SAFETY: Arc's pointer is always non-null, and we're not moving anything out of the `Arc`.
228        unsafe { NonNull::new_unchecked(Arc::into_raw(Pin::into_inner_unchecked(self)).cast_mut()) }
229    }
230}
231
232/// Potential well, representing a generic container.
233///
234/// Useful for recursive data structures, since it avoids recursive types.
235///
236/// # Examples
237///
238/// Atomic linked list via [`PotentialWell`]:
239///
240/// ```
241/// use potential_well::{PotentialWell, PotentialAtomicOption};
242///
243/// struct Link<T, W: PotentialWell = Box<()>> {
244///     data: T,
245///     next: PotentialAtomicOption<Link<T, W>, W>
246/// }
247/// struct List<T, W: PotentialWell = Box<()>> {
248///     root: PotentialAtomicOption<Link<T, W>, W>,
249/// }
250///
251/// let list: List<u32> = List {
252///     root: PotentialAtomicOption::some(Box::new(Link {
253///         data: 1,
254///         next: PotentialAtomicOption::some(Box::new(Link {
255///             data: 2,
256///             next: PotentialAtomicOption::some(Box::new(Link {
257///                 data: 3,
258///                 next: PotentialAtomicOption::none(),
259///             }))
260///         })),
261///     })),
262/// };
263///
264/// // no Drop implementation needed!
265/// drop(list);
266/// ```
267///
268/// Without [`PotentialWell`], you immediately run into trouble:
269///
270/// ```compile_fail
271/// use potential_well::{Well, AtomicOption};
272///
273/// // recursive type: Link<T, Box<Link<T, Box<Link<T, ...>>>>>
274/// struct Link<T, W: Well<Target = Link<T, Self>>> {
275///     data: T,
276///     next: AtomicOption<W>,
277/// }
278/// struct List<T, W: Well<Target = Link<T, Self>>> {
279///     root: AtomicOption<W>,
280/// }
281///
282/// let list: List<u32, Box<_>> = List {
283///     root: AtomicOption::some(Box::new(Link {
284///         data: 1,
285///         next: AtomicOption::some(Box::new(Link {
286///             data: 2,
287///             next: AtomicOption::some(Box::new(Link {
288///                 data: 3,
289///                 next: AtomicOption::none(),
290///             }))
291///         })),
292///     })),
293/// };
294/// ```
295pub trait PotentialWell {
296    /// Makes a well of a particular type.
297    type Well<T>: Well<Target = T>;
298
299    /// Makes that well.
300    fn new<T>(data: T) -> Self::Well<T>;
301}
302
303#[cfg(any(test, feature = "alloc"))]
304impl PotentialWell for Box<()> {
305    type Well<T> = Box<T>;
306
307    #[inline]
308    fn new<T>(data: T) -> Box<T> {
309        Box::new(data)
310    }
311}
312
313#[cfg(any(test, feature = "alloc"))]
314impl PotentialWell for Pin<Box<()>> {
315    type Well<T> = Pin<Box<T>>;
316
317    #[inline]
318    fn new<T>(data: T) -> Pin<Box<T>> {
319        Box::pin(data)
320    }
321}
322
323#[cfg(feature = "alloc")]
324impl PotentialWell for Rc<()> {
325    type Well<T> = Rc<T>;
326
327    #[inline]
328    fn new<T>(data: T) -> Rc<T> {
329        Rc::new(data)
330    }
331}
332
333#[cfg(feature = "alloc")]
334impl PotentialWell for Pin<Rc<()>> {
335    type Well<T> = Pin<Rc<T>>;
336
337    #[inline]
338    fn new<T>(data: T) -> Pin<Rc<T>> {
339        Rc::pin(data)
340    }
341}
342
343#[cfg(feature = "alloc")]
344impl PotentialWell for Arc<()> {
345    type Well<T> = Arc<T>;
346
347    #[inline]
348    fn new<T>(data: T) -> Arc<T> {
349        Arc::new(data)
350    }
351}
352
353#[cfg(feature = "alloc")]
354impl PotentialWell for Pin<Arc<()>> {
355    type Well<T> = Pin<Arc<T>>;
356
357    #[inline]
358    fn new<T>(data: T) -> Pin<Arc<T>> {
359        Arc::pin(data)
360    }
361}
362
363/// Gets a well from a [`PotentialWell`].
364///
365/// In case you haven't gotten the joke by now, an "atom in a box" is called a [potential well] in
366/// physics, and well, kinetic energy is the opposite of potential energy.
367///
368/// It's a bad joke. But this type shouldn't be necessary unless you're writing *really* generic
369/// code, since most of the time, you'll be using one of the many aliases for [`PotentialAtomic`]
370/// and [`PotentialAtomicOption`], which will just turn something like
371/// <code>[KineticWell]&lt;T, W&lt;()&gt;&gt;</code> into <code>W&lt;T&gt;</code>.
372///
373/// [potential well]: https://en.wikipedia.org/wiki/Potential_well
374pub type KineticWell<T, W> = <W as PotentialWell>::Well<T>;
375
376/// Alias for <code>[PotentialAtomic]&lt;T, [Box]&lt;()&gt;&gt;</code>
377#[cfg(feature = "alloc")]
378pub type AtomicBox<T> = PotentialAtomic<T, Box<()>>;
379
380/// Alias for <code>[PotentialAtomic]&lt;T, [Pin]&lt;[Box]&lt;()&gt;&gt;&gt;</code>
381#[cfg(feature = "alloc")]
382pub type AtomicPinBox<T> = PotentialAtomic<T, Pin<Box<()>>>;
383
384/// Alias for <code>[PotentialAtomic]&lt;T, [Rc]&lt;()&gt;&gt;</code>
385#[cfg(feature = "alloc")]
386pub type AtomicRc<T> = PotentialAtomic<T, Rc<()>>;
387
388/// Alias for <code>[PotentialAtomic]&lt;T, [Pin]&lt;[Rc]&lt;()&gt;&gt;&gt;</code>
389#[cfg(feature = "alloc")]
390pub type AtomicPinRc<T> = PotentialAtomic<T, Pin<Rc<()>>>;
391
392/// Alias for <code>[PotentialAtomic]&lt;T, [Arc]&lt;()&gt;&gt;</code>
393#[cfg(feature = "alloc")]
394pub type AtomicArc<T> = PotentialAtomic<T, Arc<()>>;
395
396/// Alias for <code>[PotentialAtomic]&lt;T, [Pin]&lt;[Arc]&lt;()&gt;&gt;&gt;</code>
397#[cfg(feature = "alloc")]
398pub type AtomicPinArc<T> = PotentialAtomic<T, Pin<Arc<()>>>;
399
400/// Alias for <code>[PotentialAtomicOption]&lt;T, [Box]&lt;()&gt;&gt;</code>
401#[cfg(feature = "alloc")]
402pub type AtomicOptionBox<T> = PotentialAtomicOption<T, Box<()>>;
403
404/// Alias for <code>[PotentialAtomicOption]&lt;T, [Pin]&lt;[Box]&lt;()&gt;&gt;&gt;</code>
405#[cfg(feature = "alloc")]
406pub type AtomicOptionPinBox<T> = PotentialAtomicOption<T, Pin<Box<()>>>;
407
408/// Alias for <code>[PotentialAtomicOption]&lt;T, [Rc]&lt;()&gt;&gt;</code>
409#[cfg(feature = "alloc")]
410pub type AtomicOptionRc<T> = PotentialAtomicOption<T, Rc<()>>;
411
412/// Alias for <code>[PotentialAtomicOption]&lt;T, [Pin]&lt;[Rc]&lt;()&gt;&gt;&gt;</code>
413#[cfg(feature = "alloc")]
414pub type AtomicOptionPinRc<T> = PotentialAtomicOption<T, Pin<Rc<()>>>;
415
416/// Alias for <code>[PotentialAtomicOption]&lt;T, [Arc]&lt;()&gt;&gt;</code>
417#[cfg(feature = "alloc")]
418pub type AtomicOptionArc<T> = PotentialAtomicOption<T, Arc<()>>;
419
420/// Alias for <code>[PotentialAtomicOption]&lt;T, [Pin]&lt;[Arc]&lt;()&gt;&gt;&gt;</code>
421#[cfg(feature = "alloc")]
422pub type AtomicOptionPinArc<T> = PotentialAtomicOption<T, Pin<Arc<()>>>;