@@ -69,7 +69,8 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
6969use std:: fmt;
7070use std:: future:: Future ;
7171use std:: marker:: PhantomData ;
72- use std:: mem:: { self , MaybeUninit } ;
72+ use std:: mem:: { self , ManuallyDrop , MaybeUninit } ;
73+ use std:: ops:: DerefMut ;
7374use std:: pin:: { Pin , pin} ;
7475use std:: ptr:: { self , NonNull } ;
7576use std:: slice;
@@ -1293,27 +1294,27 @@ impl Instance {
12931294
12941295 struct Dropper < ' a , T : ' static , V > {
12951296 store : StoreContextMut < ' a , T > ,
1296- value : Option < V > ,
1297+ value : ManuallyDrop < V > ,
12971298 }
12981299
12991300 impl < ' a , T , V > Drop for Dropper < ' a , T , V > {
13001301 fn drop ( & mut self ) {
1301- let value = self . value . take ( ) ;
1302- tls:: set ( self . store . 0 . traitobj_mut ( ) , move || drop ( value) ) ;
1302+ tls:: set ( self . store . 0 . traitobj_mut ( ) , || {
1303+ // SAFETY: Here we drop the value without moving it for the
1304+ // first and only time -- per the contract for `Drop::drop`,
1305+ // this code won't run again.
1306+ unsafe { ManuallyDrop :: drop ( & mut self . value ) }
1307+ } ) ;
13031308 }
13041309 }
13051310
13061311 let accessor = & Accessor :: new ( token, Some ( self ) ) ;
13071312 let dropper = & mut Dropper {
13081313 store,
1309- value : Some ( fun ( accessor) ) ,
1314+ value : ManuallyDrop :: new ( fun ( accessor) ) ,
13101315 } ;
1311- // SAFETY: `dropper` is a local, non-escaping variable and we do not
1312- // move its `value` field until it is dropped.
1313- //
1314- // TODO: Could/should we make this safe using some combination of `pin!`
1315- // and `pin_project!`?
1316- let future = unsafe { Pin :: new_unchecked ( dropper. value . as_mut ( ) . unwrap ( ) ) } ;
1316+ // SAFETY: We never move `dropper` nor its `value` field.
1317+ let future = unsafe { Pin :: new_unchecked ( dropper. value . deref_mut ( ) ) } ;
13171318
13181319 self . poll_until ( dropper. store . as_context_mut ( ) , future)
13191320 . await
0 commit comments