@@ -34,8 +34,12 @@ pub struct DropGuard<T, F>
3434where
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
4145impl < T , F > DropGuard < T , F >
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