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. It is typically preferred to call
67 /// this function instead of `mem::forget` because it will return the stored
68 /// value and drop variables captured by the closure instead of leaking their
69 /// owned resources.
70 ///
71 /// # Example
72 ///
73 /// ```rust
74 /// # #![allow(unused)]
75 /// #![feature(drop_guard)]
76 ///
77 /// use std::mem::DropGuard;
78 ///
79 /// let value = String::from("Nori likes chicken");
80 /// let guard = DropGuard::new(value, |s| println!("{s}"));
81 /// assert_eq!(guard.dismiss(), "Nori likes chicken");
82 /// ```
83 #[unstable(feature = "drop_guard", issue = "144426")]
84 #[inline]
85 pub fn dismiss(self) -> T {
86 // First we ensure that dropping the guard will not trigger
87 // its destructor
88 let mut this = ManuallyDrop::new(self);
89
90 // Next we manually read the stored value from the guard.
91 //
92 // SAFETY: this is safe because we've taken ownership of the guard.
93 let value = unsafe { ManuallyDrop::take(&mut this.inner) };
94
95 // Finally we drop the stored closure. We do this *after* having read
96 // the value, so that even if the closure's `drop` function panics,
97 // unwinding still tries to drop the value.
98 //
99 // SAFETY: this is safe because we've taken ownership of the guard.
100 unsafe { ManuallyDrop::drop(&mut this.f) };
101 value
102 }
103}
104
105#[unstable(feature = "drop_guard", issue = "144426")]
106impl<T, F> Deref for DropGuard<T, F>
107where
108 F: FnOnce(T),
109{
110 type Target = T;
111
112 fn deref(&self) -> &T {
113 &*self.inner
114 }
115}
116
117#[unstable(feature = "drop_guard", issue = "144426")]
118impl<T, F> DerefMut for DropGuard<T, F>
119where
120 F: FnOnce(T),
121{
122 fn deref_mut(&mut self) -> &mut T {
123 &mut *self.inner
124 }
125}
126
127#[unstable(feature = "drop_guard", issue = "144426")]
128impl<T, F> Drop for DropGuard<T, F>
129where
130 F: FnOnce(T),
131{
132 fn drop(&mut self) {
133 // SAFETY: `DropGuard` is in the process of being dropped.
134 let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
135
136 // SAFETY: `DropGuard` is in the process of being dropped.
137 let f = unsafe { ManuallyDrop::take(&mut self.f) };
138
139 f(inner);
140 }
141}
142
143#[unstable(feature = "drop_guard", issue = "144426")]
144impl<T, F> Debug for DropGuard<T, F>
145where
146 T: Debug,
147 F: FnOnce(T),
148{
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 fmt::Debug::fmt(&**self, f)
151 }
152}