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]<T, W<()>></code> into <code>W<T></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]<T, [Box]<()>></code>
465#[cfg(feature = "alloc")]
466pub type AtomicBox<T> = PotentialAtomic<T, Box<()>>;
467
468/// Alias for <code>[PotentialAtomic]<T, [Pin]<[Box]<()>>></code>
469#[cfg(feature = "alloc")]
470pub type AtomicPinBox<T> = PotentialAtomic<T, Pin<Box<()>>>;
471
472/// Alias for <code>[PotentialAtomic]<T, [Rc]<()>></code>
473#[cfg(feature = "alloc")]
474pub type AtomicRc<T> = PotentialAtomic<T, Rc<()>>;
475
476/// Alias for <code>[PotentialAtomic]<T, [Pin]<[Rc]<()>>></code>
477#[cfg(feature = "alloc")]
478pub type AtomicPinRc<T> = PotentialAtomic<T, Pin<Rc<()>>>;
479
480/// Alias for <code>[PotentialAtomic]<T, [Arc]<()>></code>
481#[cfg(feature = "alloc")]
482pub type AtomicArc<T> = PotentialAtomic<T, Arc<()>>;
483
484/// Alias for <code>[PotentialAtomic]<T, [Pin]<[Arc]<()>>></code>
485#[cfg(feature = "alloc")]
486pub type AtomicPinArc<T> = PotentialAtomic<T, Pin<Arc<()>>>;
487
488/// Alias for <code>[PotentialAtomicOption]<T, [Box]<()>></code>
489#[cfg(feature = "alloc")]
490pub type AtomicOptionBox<T> = PotentialAtomicOption<T, Box<()>>;
491
492/// Alias for <code>[PotentialAtomicOption]<T, [Pin]<[Box]<()>>></code>
493#[cfg(feature = "alloc")]
494pub type AtomicOptionPinBox<T> = PotentialAtomicOption<T, Pin<Box<()>>>;
495
496/// Alias for <code>[PotentialAtomicOption]<T, [Rc]<()>></code>
497#[cfg(feature = "alloc")]
498pub type AtomicOptionRc<T> = PotentialAtomicOption<T, Rc<()>>;
499
500/// Alias for <code>[PotentialAtomicOption]<T, [Pin]<[Rc]<()>>></code>
501#[cfg(feature = "alloc")]
502pub type AtomicOptionPinRc<T> = PotentialAtomicOption<T, Pin<Rc<()>>>;
503
504/// Alias for <code>[PotentialAtomicOption]<T, [Arc]<()>></code>
505#[cfg(feature = "alloc")]
506pub type AtomicOptionArc<T> = PotentialAtomicOption<T, Arc<()>>;
507
508/// Alias for <code>[PotentialAtomicOption]<T, [Pin]<[Arc]<()>>></code>
509#[cfg(feature = "alloc")]
510pub type AtomicOptionPinArc<T> = PotentialAtomicOption<T, Pin<Arc<()>>>;