@@ -82,19 +82,19 @@ pub struct Undo<T, F>
8282where
8383 F : FnOnce ( T ) ,
8484{
85- inner : Option < T > ,
86- undo : Option < F > ,
85+ inner : mem :: ManuallyDrop < T > ,
86+ undo : mem :: ManuallyDrop < F > ,
8787}
8888
8989impl < T , F > Drop for Undo < T , F >
9090where
9191 F : FnOnce ( T ) ,
9292{
9393 fn drop ( & mut self ) {
94- if let Some ( inner ) = self . inner . take ( ) {
95- let undo = self . undo . take ( ) . unwrap ( ) ;
96- undo ( inner ) ;
97- }
94+ // Safety: These `ManuallyDrop` fields will not be used again.
95+ let inner = unsafe { mem :: ManuallyDrop :: take ( & mut self . inner ) } ;
96+ let undo = unsafe { mem :: ManuallyDrop :: take ( & mut self . undo ) } ;
97+ undo ( inner ) ;
9898 }
9999}
100100
@@ -118,7 +118,7 @@ where
118118 type Target = T ;
119119
120120 fn deref ( & self ) -> & Self :: Target {
121- self . inner . as_ref ( ) . unwrap ( )
121+ & self . inner
122122 }
123123}
124124
@@ -127,7 +127,7 @@ where
127127 F : FnOnce ( T ) ,
128128{
129129 fn deref_mut ( & mut self ) -> & mut Self :: Target {
130- self . inner . as_mut ( ) . unwrap ( )
130+ & mut self . inner
131131 }
132132}
133133
@@ -141,16 +141,23 @@ where
141141 /// when dropped, unless the guard is disabled via `Undo::commit`.
142142 pub fn new ( inner : T , undo : F ) -> Self {
143143 Self {
144- inner : Some ( inner) ,
145- undo : Some ( undo) ,
144+ inner : mem :: ManuallyDrop :: new ( inner) ,
145+ undo : mem :: ManuallyDrop :: new ( undo) ,
146146 }
147147 }
148148
149149 /// Disable this `Undo` and return its inner value.
150150 ///
151151 /// This `Undo`'s cleanup function will never be called.
152152 pub fn commit ( mut guard : Self ) -> T {
153- let inner = guard. inner . take ( ) . unwrap ( ) ;
153+ // Safety: These `ManuallyDrop` fields will not be used again.
154+ let inner = unsafe {
155+ // Make sure to drop `undo`, even though we aren't calling it, to
156+ // avoid leaking closed-over `Arc`s, for example.
157+ mem:: ManuallyDrop :: drop ( & mut guard. undo ) ;
158+
159+ mem:: ManuallyDrop :: take ( & mut guard. inner )
160+ } ;
154161 mem:: forget ( guard) ;
155162 inner
156163 }
0 commit comments