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::{
12        boxed::Box,
13        rc::{self, Rc},
14        sync::{self as arc, Arc},
15    },
16};
17
18/// Place that can store a smart pointer.
19///
20/// # Safety
21///
22/// Types that implement this trait assert that the [`insert`] and [`remove`] methods are true
23/// inverses of each other with no side effects.
24///
25/// [`insert`]: Well::insert
26/// [`remove`]: Well::remove
27pub unsafe trait Well {
28    /// Data stored in the pointer.
29    type Target;
30
31    /// Put the data back into the well.
32    ///
33    /// # Safety
34    ///
35    /// The pointer passed to [`insert`] must previously have been received from [`remove`].
36    ///
37    /// [`insert`]: Well::insert
38    /// [`remove`]: Well::remove
39    unsafe fn insert(ptr: NonNull<Self::Target>) -> Self;
40
41    /// Take the data out of the well.
42    fn remove(self) -> NonNull<Self::Target>;
43}
44
45/// Gets the target for a [`Well`].
46pub type Bucket<W> = <W as Well>::Target;
47
48/// Implementation of trait alias that uses trait aliases.
49#[cfg(feature = "nightly")]
50macro_rules! trait_alias {
51    (
52        $(#[$attr:meta])*
53        $vis:vis trait $t:ident = ($($bound:tt)*);
54    ) => {
55        $(#[$attr])*
56        ///
57        /// Implemented as a trait alias with the `nightly` feature,
58        /// and an automatically-implemented trait otherwise.
59        $vis trait $t = $($bound)*;
60    }
61}
62
63/// Implementation of trait alias that uses traits.
64#[cfg(not(feature = "nightly"))]
65macro_rules! trait_alias {
66    (
67        $(#[$attr:meta])*
68        $vis:vis trait $t:ident = ($($bound:tt)*);
69    ) => {
70        $(#[$attr])*
71        ///
72        /// Implemented as a trait alias with the `nightly` feature,
73        /// and an automatically-implemented trait otherwise.
74        $vis trait $t: $($bound)* {}
75        impl<T: $($bound)*> $t for T {}
76    }
77}
78
79/// Smart pointer without direct access to its data.
80///
81/// # Safety
82///
83/// Implementors of this trait assert that [`insert`] and [`remove`] calls of themselves and their
84/// [`Access`] variant can be interchanged as long as the number of "weak" and "strong" versions
85/// remain the same.
86///
87/// [`Access`]: WeakWell::Access
88/// [`insert`]: Well::insert
89/// [`remove`]: Well::remove
90pub unsafe trait WeakWell: Well {
91    /// Smart pointer that can directly access data.
92    type Access: StrongWell + Deref<Target = Self::Target>;
93
94    /// Attempts to access data inside the well.
95    fn access(&self) -> Option<Self::Access>;
96}
97
98/// Smart pointer with direct access to its data.
99///
100/// # Safety
101///
102/// Types that implement this trait assert, in addition to the requirements of [`Well`], that the
103/// pointers returned/received by [`insert`] and [`remove`] are also valid to deref directly
104/// whenever a valid reference to the pointer is obtained, *and* that if they implement
105/// [`DerefMut`], the same applies to mutable dereferences.
106///
107/// Additionally, implementations guarantee that their contents are implicitly pinned, and thus
108/// [`Pin::new_unchecked`] and [`Pin::into_inner_unchecked`] have the correct semantics for the
109/// generic [`Pin`]ned implementation.
110///
111/// [`insert`]: Well::insert
112/// [`remove`]: Well::remove
113pub unsafe trait StrongWell:
114    Deref<Target: Sized> + Well<Target = <Self as Deref>::Target>
115{
116}
117
118// SAFETY: Ensured by contract for `StrongWell`.
119unsafe impl<W: StrongWell> Well for Pin<W> {
120    type Target = Bucket<W>;
121
122    #[inline]
123    unsafe fn insert(ptr: NonNull<Bucket<W>>) -> Pin<W> {
124        // SAFETY: Ensured by contract for `StrongWell`.
125        unsafe { Pin::new_unchecked(W::insert(ptr)) }
126    }
127
128    #[inline]
129    fn remove(self) -> NonNull<Bucket<W>> {
130        // SAFETY: Ensured by contract for `StrongWell`.
131        unsafe { Pin::into_inner_unchecked(self).remove() }
132    }
133}
134// SAFETY: Ensured by contract for `StrongWell`.
135unsafe impl<W: StrongWell> StrongWell for Pin<W> {}
136
137trait_alias! {
138    /// Alias for <code>[StrongWell] + [DerefMut]</code>.
139    ///
140    /// Since [`StrongWell`] is unsafe to implement, it can assert that its guarantees apply to
141    /// [`DerefMut`] implementations as well.
142    pub trait StrongWellMut = (StrongWell + DerefMut);
143}
144
145// SAFETY: `NonNull::from` and `NonNull::as_ref` are direct inverses.
146unsafe impl<'w, T> Well for &'w T {
147    type Target = T;
148
149    #[inline]
150    unsafe fn insert(ptr: NonNull<T>) -> &'w T {
151        // SAFETY: Ensured by caller.
152        unsafe { ptr.as_ref() }
153    }
154
155    #[inline]
156    fn remove(self) -> NonNull<T> {
157        NonNull::from(self)
158    }
159}
160// SAFETY: `Deref for &T` is stable.
161unsafe impl<T> StrongWell for &T {}
162
163// SAFETY: `NonNull::from` and `NonNull::as_mut` are direct inverses.
164unsafe impl<T> Well for &mut T {
165    type Target = T;
166
167    #[inline]
168    unsafe fn insert(mut ptr: NonNull<T>) -> Self {
169        // SAFETY: Ensured by caller.
170        unsafe { ptr.as_mut() }
171    }
172
173    #[inline]
174    fn remove(self) -> NonNull<T> {
175        NonNull::from(self)
176    }
177}
178// SAFETY: `Deref for &mut T` is stable.
179unsafe impl<T> StrongWell for &mut T {}
180
181#[cfg(any(test, feature = "alloc"))]
182// SAFETY: `Box::from_raw` and `Box::into_raw` are direct inverses.
183unsafe impl<T> Well for Box<T> {
184    type Target = T;
185
186    #[inline]
187    unsafe fn insert(ptr: NonNull<T>) -> Self {
188        // SAFETY: Ensured by caller.
189        unsafe { Box::from_raw(ptr.as_ptr()) }
190    }
191
192    #[inline]
193    fn remove(self) -> NonNull<T> {
194        // SAFETY: Box's pointer is always non-null.
195        unsafe { NonNull::new_unchecked(Box::into_raw(self)) }
196    }
197}
198#[cfg(feature = "alloc")]
199// SAFETY: `Deref for Box<T>` is stable.
200unsafe impl<T> StrongWell for Box<T> {}
201
202#[cfg(feature = "alloc")]
203// SAFETY: `Rc::from_raw` and `Rc::into_raw` are direct inverses.
204unsafe impl<T> Well for Rc<T> {
205    type Target = T;
206
207    #[inline]
208    unsafe fn insert(ptr: NonNull<T>) -> Self {
209        // SAFETY: Ensured by caller.
210        unsafe { Rc::from_raw(ptr.as_ptr()) }
211    }
212
213    #[inline]
214    fn remove(self) -> NonNull<T> {
215        // SAFETY: Rc's pointer is always non-null.
216        unsafe { NonNull::new_unchecked(Rc::into_raw(self).cast_mut()) }
217    }
218}
219#[cfg(feature = "alloc")]
220// SAFETY: `Deref for Rc<T>` is stable.
221unsafe impl<T> StrongWell for Rc<T> {}
222
223#[cfg(feature = "alloc")]
224// SAFETY: `Weak::from_raw` and `Weak::into_raw` are direct inverses.
225unsafe impl<T> Well for rc::Weak<T> {
226    type Target = T;
227
228    #[inline]
229    unsafe fn insert(ptr: NonNull<T>) -> Self {
230        // SAFETY: Ensured by caller.
231        unsafe { rc::Weak::from_raw(ptr.as_ptr()) }
232    }
233
234    #[inline]
235    fn remove(self) -> NonNull<T> {
236        // SAFETY: WeakArc's pointer is always non-null.
237        unsafe { NonNull::new_unchecked(rc::Weak::into_raw(self).cast_mut()) }
238    }
239}
240#[cfg(feature = "alloc")]
241// SAFETY: `Rc` and `Weak` share the same pointers.
242unsafe impl<T> WeakWell for rc::Weak<T> {
243    type Access = Rc<T>;
244
245    #[inline]
246    fn access(&self) -> Option<Rc<T>> {
247        self.upgrade()
248    }
249}
250
251#[cfg(feature = "alloc")]
252// SAFETY: `Arc::from_raw` and `Arc::into_raw` are direct inverses.
253unsafe impl<T> Well for Arc<T> {
254    type Target = T;
255
256    #[inline]
257    unsafe fn insert(ptr: NonNull<T>) -> Self {
258        // SAFETY: Ensured by caller.
259        unsafe { Arc::from_raw(ptr.as_ptr()) }
260    }
261
262    #[inline]
263    fn remove(self) -> NonNull<T> {
264        // SAFETY: Arc's pointer is always non-null.
265        unsafe { NonNull::new_unchecked(Arc::into_raw(self).cast_mut()) }
266    }
267}
268#[cfg(feature = "alloc")]
269// SAFETY: `Deref for Arc<T>` is stable.
270unsafe impl<T> StrongWell for Arc<T> {}
271
272#[cfg(feature = "alloc")]
273// SAFETY: `Weak::from_raw` and `Weak::into_raw` are direct inverses.
274unsafe impl<T> Well for arc::Weak<T> {
275    type Target = T;
276
277    #[inline]
278    unsafe fn insert(ptr: NonNull<T>) -> Self {
279        // SAFETY: Ensured by caller.
280        unsafe { arc::Weak::from_raw(ptr.as_ptr()) }
281    }
282
283    #[inline]
284    fn remove(self) -> NonNull<T> {
285        // SAFETY: WeakArc's pointer is always non-null.
286        unsafe { NonNull::new_unchecked(arc::Weak::into_raw(self).cast_mut()) }
287    }
288}
289#[cfg(feature = "alloc")]
290// SAFETY: `Arc` and `Weak` share the same pointers.
291unsafe impl<T> WeakWell for arc::Weak<T> {
292    type Access = Arc<T>;
293
294    #[inline]
295    fn access(&self) -> Option<Arc<T>> {
296        self.upgrade()
297    }
298}
299
300/// Potential well, representing a generic container.
301///
302/// Useful for recursive data structures, since it avoids recursive types.
303///
304/// # Examples
305///
306/// Atomic linked list via [`PotentialWell`]:
307///
308/// ```
309/// use potential_well::{PotentialWell, PotentialAtomicOption};
310///
311/// struct Link<T, W: PotentialWell = Box<()>> {
312///     data: T,
313///     next: PotentialAtomicOption<Link<T, W>, W>
314/// }
315/// struct List<T, W: PotentialWell = Box<()>> {
316///     root: PotentialAtomicOption<Link<T, W>, W>,
317/// }
318///
319/// let list: List<u32> = List {
320///     root: PotentialAtomicOption::some(Box::new(Link {
321///         data: 1,
322///         next: PotentialAtomicOption::some(Box::new(Link {
323///             data: 2,
324///             next: PotentialAtomicOption::some(Box::new(Link {
325///                 data: 3,
326///                 next: PotentialAtomicOption::none(),
327///             }))
328///         })),
329///     })),
330/// };
331///
332/// // no Drop implementation needed!
333/// drop(list);
334/// ```
335///
336/// Without [`PotentialWell`], you immediately run into trouble:
337///
338/// ```compile_fail
339/// use potential_well::{Well, AtomicOption};
340///
341/// // recursive type: Link<T, Box<Link<T, Box<Link<T, ...>>>>>
342/// struct Link<T, W: Well<Target = Link<T, Self>>> {
343///     data: T,
344///     next: AtomicOption<W>,
345/// }
346/// struct List<T, W: Well<Target = Link<T, Self>>> {
347///     root: AtomicOption<W>,
348/// }
349///
350/// let list: List<u32, Box<_>> = List {
351///     root: AtomicOption::some(Box::new(Link {
352///         data: 1,
353///         next: AtomicOption::some(Box::new(Link {
354///             data: 2,
355///             next: AtomicOption::some(Box::new(Link {
356///                 data: 3,
357///                 next: AtomicOption::none(),
358///             }))
359///         })),
360///     })),
361/// };
362/// ```
363pub trait PotentialWell {
364    /// Makes a well of a particular type.
365    type Well<T>: Well<Target = T>;
366
367    /// Makes that well.
368    fn new<T>(data: T) -> Self::Well<T>;
369}
370
371#[cfg(any(test, feature = "alloc"))]
372impl PotentialWell for Box<()> {
373    type Well<T> = Box<T>;
374
375    #[inline]
376    fn new<T>(data: T) -> Box<T> {
377        Box::new(data)
378    }
379}
380
381#[cfg(any(test, feature = "alloc"))]
382impl PotentialWell for Pin<Box<()>> {
383    type Well<T> = Pin<Box<T>>;
384
385    #[inline]
386    fn new<T>(data: T) -> Pin<Box<T>> {
387        Box::pin(data)
388    }
389}
390
391#[cfg(feature = "alloc")]
392impl PotentialWell for Rc<()> {
393    type Well<T> = Rc<T>;
394
395    #[inline]
396    fn new<T>(data: T) -> Rc<T> {
397        Rc::new(data)
398    }
399}
400
401#[cfg(feature = "alloc")]
402impl PotentialWell for Pin<Rc<()>> {
403    type Well<T> = Pin<Rc<T>>;
404
405    #[inline]
406    fn new<T>(data: T) -> Pin<Rc<T>> {
407        Rc::pin(data)
408    }
409}
410
411#[cfg(feature = "alloc")]
412impl PotentialWell for rc::Weak<()> {
413    type Well<T> = rc::Weak<T>;
414
415    #[inline]
416    fn new<T>(_: T) -> rc::Weak<T> {
417        rc::Weak::default()
418    }
419}
420
421#[cfg(feature = "alloc")]
422impl PotentialWell for Arc<()> {
423    type Well<T> = Arc<T>;
424
425    #[inline]
426    fn new<T>(data: T) -> Arc<T> {
427        Arc::new(data)
428    }
429}
430
431#[cfg(feature = "alloc")]
432impl PotentialWell for Pin<Arc<()>> {
433    type Well<T> = Pin<Arc<T>>;
434
435    #[inline]
436    fn new<T>(data: T) -> Pin<Arc<T>> {
437        Arc::pin(data)
438    }
439}
440
441#[cfg(feature = "alloc")]
442impl PotentialWell for arc::Weak<()> {
443    type Well<T> = arc::Weak<T>;
444
445    #[inline]
446    fn new<T>(_: T) -> arc::Weak<T> {
447        arc::Weak::default()
448    }
449}
450
451/// Gets a well from a [`PotentialWell`].
452///
453/// In case you haven't gotten the joke by now, an "atom in a box" is called a [potential well] in
454/// physics, and well, kinetic energy is the opposite of potential energy.
455///
456/// It's a bad joke. But this type shouldn't be necessary unless you're writing *really* generic
457/// code, since most of the time, you'll be using one of the many aliases for [`PotentialAtomic`]
458/// and [`PotentialAtomicOption`], which will just turn something like
459/// <code>[KineticWell]&lt;T, W&lt;()&gt;&gt;</code> into <code>W&lt;T&gt;</code>.
460///
461/// [potential well]: https://en.wikipedia.org/wiki/Potential_well
462pub type KineticWell<T, W> = <W as PotentialWell>::Well<T>;
463
464/// Alias for <code>[PotentialAtomic]&lt;T, [Box]&lt;()&gt;&gt;</code>
465#[cfg(feature = "alloc")]
466pub type AtomicBox<T> = PotentialAtomic<T, Box<()>>;
467
468/// Alias for <code>[PotentialAtomic]&lt;T, [Pin]&lt;[Box]&lt;()&gt;&gt;&gt;</code>
469#[cfg(feature = "alloc")]
470pub type AtomicPinBox<T> = PotentialAtomic<T, Pin<Box<()>>>;
471
472/// Alias for <code>[PotentialAtomic]&lt;T, [Rc]&lt;()&gt;&gt;</code>
473#[cfg(feature = "alloc")]
474pub type AtomicRc<T> = PotentialAtomic<T, Rc<()>>;
475
476/// Alias for <code>[PotentialAtomic]&lt;T, [Pin]&lt;[Rc]&lt;()&gt;&gt;&gt;</code>
477#[cfg(feature = "alloc")]
478pub type AtomicPinRc<T> = PotentialAtomic<T, Pin<Rc<()>>>;
479
480/// Alias for <code>[PotentialAtomic]&lt;T, [Arc]&lt;()&gt;&gt;</code>
481#[cfg(feature = "alloc")]
482pub type AtomicArc<T> = PotentialAtomic<T, Arc<()>>;
483
484/// Alias for <code>[PotentialAtomic]&lt;T, [Pin]&lt;[Arc]&lt;()&gt;&gt;&gt;</code>
485#[cfg(feature = "alloc")]
486pub type AtomicPinArc<T> = PotentialAtomic<T, Pin<Arc<()>>>;
487
488/// Alias for <code>[PotentialAtomicOption]&lt;T, [Box]&lt;()&gt;&gt;</code>
489#[cfg(feature = "alloc")]
490pub type AtomicOptionBox<T> = PotentialAtomicOption<T, Box<()>>;
491
492/// Alias for <code>[PotentialAtomicOption]&lt;T, [Pin]&lt;[Box]&lt;()&gt;&gt;&gt;</code>
493#[cfg(feature = "alloc")]
494pub type AtomicOptionPinBox<T> = PotentialAtomicOption<T, Pin<Box<()>>>;
495
496/// Alias for <code>[PotentialAtomicOption]&lt;T, [Rc]&lt;()&gt;&gt;</code>
497#[cfg(feature = "alloc")]
498pub type AtomicOptionRc<T> = PotentialAtomicOption<T, Rc<()>>;
499
500/// Alias for <code>[PotentialAtomicOption]&lt;T, [Pin]&lt;[Rc]&lt;()&gt;&gt;&gt;</code>
501#[cfg(feature = "alloc")]
502pub type AtomicOptionPinRc<T> = PotentialAtomicOption<T, Pin<Rc<()>>>;
503
504/// Alias for <code>[PotentialAtomicOption]&lt;T, [Arc]&lt;()&gt;&gt;</code>
505#[cfg(feature = "alloc")]
506pub type AtomicOptionArc<T> = PotentialAtomicOption<T, Arc<()>>;
507
508/// Alias for <code>[PotentialAtomicOption]&lt;T, [Pin]&lt;[Arc]&lt;()&gt;&gt;&gt;</code>
509#[cfg(feature = "alloc")]
510pub type AtomicOptionPinArc<T> = PotentialAtomicOption<T, Pin<Arc<()>>>;