Skip to content

Commit 2a1c764

Browse files
committed
Refactor DropGuard with one ManuallyDrop
1 parent 4056082 commit 2a1c764

File tree

1 file changed

+19
-26
lines changed

1 file changed

+19
-26
lines changed

library/core/src/mem/drop_guard.rs

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ pub struct DropGuard<T, F>
3434
where
3535
F: FnOnce(T),
3636
{
37-
inner: ManuallyDrop<T>,
38-
f: ManuallyDrop<F>,
37+
inner: ManuallyDrop<DropGuardInner<T, F>>,
38+
}
39+
40+
struct DropGuardInner<T, F> {
41+
value: T,
42+
f: F,
3943
}
4044

4145
impl<T, F> DropGuard<T, F>
@@ -57,8 +61,8 @@ where
5761
/// ```
5862
#[unstable(feature = "drop_guard", issue = "144426")]
5963
#[must_use]
60-
pub const fn new(inner: T, f: F) -> Self {
61-
Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) }
64+
pub const fn new(value: T, f: F) -> Self {
65+
DropGuard { inner: ManuallyDrop::new(DropGuardInner { value, f }) }
6266
}
6367

6468
/// Consumes the `DropGuard`, returning the wrapped value.
@@ -86,21 +90,14 @@ where
8690
#[unstable(feature = "drop_guard", issue = "144426")]
8791
#[inline]
8892
pub fn into_inner(guard: Self) -> T {
89-
// First we ensure that dropping the guard will not trigger
90-
// its destructor
9193
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) };
94+
// SAFETY: This ManuallyDrop is owned by another ManuallyDrop which is
95+
// dropped at the end of this function.
96+
let DropGuardInner { value, f } = unsafe { ManuallyDrop::take(&mut guard.inner) };
97+
// FIXME(#47949): `value` should drop if dropping `f` panics.
98+
// If #47949 is fixed, this can be removed.
99+
// This is tested in mem::drop_guard_always_drops_value_if_closure_drop_unwinds.
100+
drop(f);
104101
value
105102
}
106103
}
@@ -113,7 +110,7 @@ where
113110
type Target = T;
114111

115112
fn deref(&self) -> &T {
116-
&*self.inner
113+
&self.inner.value
117114
}
118115
}
119116

@@ -123,7 +120,7 @@ where
123120
F: FnOnce(T),
124121
{
125122
fn deref_mut(&mut self) -> &mut T {
126-
&mut *self.inner
123+
&mut self.inner.value
127124
}
128125
}
129126

@@ -134,12 +131,8 @@ where
134131
{
135132
fn drop(&mut self) {
136133
// 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);
134+
let DropGuardInner { value, f } = unsafe { ManuallyDrop::take(&mut self.inner) };
135+
f(value);
143136
}
144137
}
145138

0 commit comments

Comments
 (0)