Skip to main content

potential_well/
traits.rs

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