drop_move/
drop_handle.rs

1use super::*;
2
3/// A wrapper of [`T::Outer`](DropMoveTypes::Outer) that will drop by converting to `T` then
4/// dropping, rather than dropping the `T::Outer`.
5///
6/// The trouble with making `drop` be pass by move is that the `self` parameter may end up being
7/// dropped, creating infinite recursion. To avoid this, a `DropHandle` is passed to
8/// [`drop_move`](DropMove::drop_move) so that if it goes out of scope it will not create infinite
9/// recursion. This implements [`Deref`] and [`DerefMut`] for easy access to functions on
10/// `T::Outer`.
11#[derive(Debug)]
12pub struct DropHandle<T: DropMoveTypes>(ManuallyDrop<T::Outer>);
13
14impl<T: DropMoveTypes> DropHandle<T> {
15    unsafe fn take(self_: &mut Self) -> T::Outer {
16        ManuallyDrop::take(&mut self_.0)
17    }
18
19    /// Convert to the inner structure `T`.
20    ///
21    /// This is an associated function so that will not conflict with any methods of `T::Outer`,
22    /// which are accessible through [`Deref`].
23    pub fn into_inner(self_: Self) -> T {
24        Self::into_outer(self_).into()
25    }
26
27    /// Convert to the outer structure `T::Outer`. Be careful when using this function, as it is
28    /// easy to end up recursively calling `drop` on the output by accident, creating an infinite
29    /// recursive loop.
30    ///
31    /// This is an associated function so that will not conflict with any methods of `T::Outer`,
32    /// which are accessible through [`Deref`].
33    pub fn into_outer(mut self_: Self) -> T::Outer {
34        let outer = unsafe { Self::take(&mut self_) };
35        mem::forget(self_);
36        outer
37    }
38}
39
40impl<T: DropMoveTypes> From<T> for DropHandle<T> {
41    fn from(t: T) -> Self {
42        Self(ManuallyDrop::new(t.into()))
43    }
44}
45
46impl<T: DropMoveTypes> Drop for DropHandle<T> {
47    fn drop(&mut self) {
48        let _inner: T = unsafe { Self::take(self) }.into();
49
50        // Dropping the inner type avoids the drop calling drop infinite loop.
51    }
52}
53
54impl<T: DropMoveTypes> Deref for DropHandle<T> {
55    type Target = T::Outer;
56    fn deref(&self) -> &T::Outer {
57        self.0.deref()
58    }
59}
60
61impl<T: DropMoveTypes> DerefMut for DropHandle<T> {
62    fn deref_mut(&mut self) -> &mut T::Outer {
63        self.0.deref_mut()
64    }
65}