polars_utils/
with_drop.rs

1// A copy from the yet unstable library/core/src/mem/drop_guard.rs.
2
3use core::fmt::{self, Debug};
4use core::mem::ManuallyDrop;
5use core::ops::{Deref, DerefMut};
6
7pub struct WithDrop<T, F>
8where
9    F: FnOnce(T),
10{
11    inner: ManuallyDrop<T>,
12    f: ManuallyDrop<F>,
13}
14
15impl<T, F> WithDrop<T, F>
16where
17    F: FnOnce(T),
18{
19    #[must_use]
20    pub const fn new(inner: T, f: F) -> Self {
21        Self {
22            inner: ManuallyDrop::new(inner),
23            f: ManuallyDrop::new(f),
24        }
25    }
26
27    #[inline]
28    pub fn into_inner(guard: Self) -> T {
29        // First we ensure that dropping the guard will not trigger
30        // its destructor
31        let mut guard = ManuallyDrop::new(guard);
32
33        // Next we manually read the stored value from the guard.
34        //
35        // SAFETY: this is safe because we've taken ownership of the guard.
36        let value = unsafe { ManuallyDrop::take(&mut guard.inner) };
37
38        // Finally we drop the stored closure. We do this *after* having read
39        // the value, so that even if the closure's `drop` function panics,
40        // unwinding still tries to drop the value.
41        //
42        // SAFETY: this is safe because we've taken ownership of the guard.
43        unsafe { ManuallyDrop::drop(&mut guard.f) };
44        value
45    }
46}
47
48impl<T, F> Deref for WithDrop<T, F>
49where
50    F: FnOnce(T),
51{
52    type Target = T;
53
54    fn deref(&self) -> &T {
55        &self.inner
56    }
57}
58
59impl<T, F> DerefMut for WithDrop<T, F>
60where
61    F: FnOnce(T),
62{
63    fn deref_mut(&mut self) -> &mut T {
64        &mut self.inner
65    }
66}
67
68impl<T, F> Drop for WithDrop<T, F>
69where
70    F: FnOnce(T),
71{
72    fn drop(&mut self) {
73        // SAFETY: `WithDrop` is in the process of being dropped.
74        let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
75
76        // SAFETY: `WithDrop` is in the process of being dropped.
77        let f = unsafe { ManuallyDrop::take(&mut self.f) };
78
79        f(inner);
80    }
81}
82
83impl<T, F> Debug for WithDrop<T, F>
84where
85    T: Debug,
86    F: FnOnce(T),
87{
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        fmt::Debug::fmt(&**self, f)
90    }
91}