core/mem/drop_guard.rs
1use crate::fmt::{self, Debug};
2use crate::mem::ManuallyDrop;
3use crate::ops::{Deref, DerefMut};
4
5/// Wrap a value and run a closure when dropped.
6///
7/// This is useful for quickly creating destructors inline.
8///
9/// # Examples
10///
11/// ```rust
12/// # #![allow(unused)]
13/// #![feature(drop_guard)]
14///
15/// use std::mem::DropGuard;
16///
17/// {
18/// // Create a new guard around a string that will
19/// // print its value when dropped.
20/// let s = String::from("Chashu likes tuna");
21/// let mut s = DropGuard::new(s, |s| println!("{s}"));
22///
23/// // Modify the string contained in the guard.
24/// s.push_str("!!!");
25///
26/// // The guard will be dropped here, printing:
27/// // "Chashu likes tuna!!!"
28/// }
29/// ```
30#[unstable(feature = "drop_guard", issue = "144426")]
31#[doc(alias = "ScopeGuard")]
32#[doc(alias = "defer")]
33pub struct DropGuard<T, F>
34where
35 F: FnOnce(T),
36{
37 inner: ManuallyDrop<T>,
38 f: ManuallyDrop<F>,
39}
40
41impl<T, F> DropGuard<T, F>
42where
43 F: FnOnce(T),
44{
45 /// Create a new instance of `DropGuard`.
46 ///
47 /// # Example
48 ///
49 /// ```rust
50 /// # #![allow(unused)]
51 /// #![feature(drop_guard)]
52 ///
53 /// use std::mem::DropGuard;
54 ///
55 /// let value = String::from("Chashu likes tuna");
56 /// let guard = DropGuard::new(value, |s| println!("{s}"));
57 /// ```
58 #[unstable(feature = "drop_guard", issue = "144426")]
59 #[must_use]
60 pub const fn new(inner: T, f: F) -> Self {
61 Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) }
62 }
63
64 /// Consumes the `DropGuard`, returning the wrapped value.
65 ///
66 /// This will not execute the closure. This is implemented as an associated
67 /// function to prevent any potential conflicts with any other methods called
68 /// `into_inner` from the `Deref` and `DerefMut` impls.
69 ///
70 /// It is typically preferred to call this function instead of `mem::forget`
71 /// because it will return the stored value and drop variables captured
72 /// by the closure instead of leaking their owned resources.
73 ///
74 /// # Example
75 ///
76 /// ```rust
77 /// # #![allow(unused)]
78 /// #![feature(drop_guard)]
79 ///
80 /// use std::mem::DropGuard;
81 ///
82 /// let value = String::from("Nori likes chicken");
83 /// let guard = DropGuard::new(value, |s| println!("{s}"));
84 /// assert_eq!(DropGuard::into_inner(guard), "Nori likes chicken");
85 /// ```
86 #[unstable(feature = "drop_guard", issue = "144426")]
87 #[inline]
88 pub fn into_inner(guard: Self) -> T {
89 // First we ensure that dropping the guard will not trigger
90 // its destructor
91 let mut guard = ManuallyDrop::new(guard);
92
93 // Next we manually read the stored value from the guard.
94 //
95 // SAFETY: this is safe because we've taken ownership of the guard.
96 let value = unsafe { ManuallyDrop::take(&mut guard.inner) };
97
98 // Finally we drop the stored closure. We do this *after* having read
99 // the value, so that even if the closure's `drop` function panics,
100 // unwinding still tries to drop the value.
101 //
102 // SAFETY: this is safe because we've taken ownership of the guard.
103 unsafe { ManuallyDrop::drop(&mut guard.f) };
104 value
105 }
106}
107
108#[unstable(feature = "drop_guard", issue = "144426")]
109impl<T, F> Deref for DropGuard<T, F>
110where
111 F: FnOnce(T),
112{
113 type Target = T;
114
115 fn deref(&self) -> &T {
116 &*self.inner
117 }
118}
119
120#[unstable(feature = "drop_guard", issue = "144426")]
121impl<T, F> DerefMut for DropGuard<T, F>
122where
123 F: FnOnce(T),
124{
125 fn deref_mut(&mut self) -> &mut T {
126 &mut *self.inner
127 }
128}
129
130#[unstable(feature = "drop_guard", issue = "144426")]
131impl<T, F> Drop for DropGuard<T, F>
132where
133 F: FnOnce(T),
134{
135 fn drop(&mut self) {
136 // SAFETY: `DropGuard` is in the process of being dropped.
137 let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
138
139 // SAFETY: `DropGuard` is in the process of being dropped.
140 let f = unsafe { ManuallyDrop::take(&mut self.f) };
141
142 f(inner);
143 }
144}
145
146#[unstable(feature = "drop_guard", issue = "144426")]
147impl<T, F> Debug for DropGuard<T, F>
148where
149 T: Debug,
150 F: FnOnce(T),
151{
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 fmt::Debug::fmt(&**self, f)
154 }
155}