Skip to main content

leak_playground_std/
marker.rs

1//! Possible [`core::marker`] additions. Contains the proposed [`Forget`] trait.
2
3use std::{fmt::Debug, future::Future, marker::PhantomData, pin::Pin, task};
4
5/// The core trait of the destruction guarantee.
6///
7/// # Safety
8///
9/// Implement only if you know there's absolutely no possible way to
10/// forget your type.
11pub unsafe auto trait Forget {}
12
13#[doc(inline)]
14pub use Forget as Leak;
15
16/// A transparent wrapper to make your types `!Forget`
17#[repr(transparent)]
18#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct Unforget<'a, T: ?Sized> {
20    _unforget: PhantomStaticUnforget,
21    /// Inner value must be able to outlive this lifetime to be able to
22    /// be forgotten. Of course it is contravariant, since expanding it
23    /// may only disable the [`Forget`] implementation.
24    _anchor: PhantomData<fn(&'a ())>,
25    inner: T,
26}
27
28impl<T: ?Sized + Debug> Debug for Unforget<'_, T> {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        f.debug_tuple("Unforget").field(&&self.inner).finish()
31    }
32}
33
34#[doc(inline)]
35pub use Unforget as Unleak;
36
37impl<T> Unforget<'static, T> {
38    pub const fn new(inner: T) -> Self {
39        Unforget {
40            _unforget: PhantomStaticUnforget,
41            _anchor: PhantomData,
42            inner,
43        }
44    }
45}
46
47impl<'a, T> Unforget<'a, T> {
48    pub fn with_lifetime(inner: T) -> Self {
49        Unforget {
50            _unforget: PhantomStaticUnforget,
51            _anchor: PhantomData,
52            inner,
53        }
54    }
55
56    /// Get inner value.
57    pub fn into_inner(slot: Self) -> T {
58        slot.inner
59    }
60}
61
62impl<T: ?Sized> std::ops::DerefMut for Unforget<'_, T> {
63    fn deref_mut(&mut self) -> &mut Self::Target {
64        &mut self.inner
65    }
66}
67
68impl<T: ?Sized> std::ops::Deref for Unforget<'_, T> {
69    type Target = T;
70
71    fn deref(&self) -> &Self::Target {
72        &self.inner
73    }
74}
75
76impl<T: ?Sized> Future for Unforget<'_, T>
77where
78    T: Future,
79{
80    type Output = T::Output;
81
82    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
83        unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner).poll(cx) }
84    }
85}
86
87unsafe impl<'a, T: ?Sized + 'a> Forget for Unforget<'a, T> {}
88
89#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
90struct PhantomStaticUnforget;
91
92impl !Forget for PhantomStaticUnforget {}
93
94// SAFETY: borrows don't own anything
95unsafe impl<T: ?Sized> Forget for &T {}
96unsafe impl<T: ?Sized> Forget for &mut T {}
97
98// Workaround impls since we aren't inside of std
99
100// SAFETY: it is always safe to forget JoinHandle
101unsafe impl<T: 'static> Forget for std::thread::JoinHandle<T> {}
102
103#[cfg(feature = "tokio_rt")]
104#[doc(hidden)] // Nothing to document
105mod tokio_rt {
106    unsafe impl<T: 'static> super::Forget for tokio::task::JoinHandle<T> {}
107}