Skip to content

Commit 30756dc

Browse files
committed
use ManuallyDrop instead of Option in Dropper
This allows us to drop its `value` field in-place, i.e. without moving it, thereby upholding the `Pin` guarantee. Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent 23b2ab8 commit 30756dc

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

crates/wasmtime/src/runtime/component/concurrent.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
6969
use std::fmt;
7070
use std::future::Future;
7171
use std::marker::PhantomData;
72-
use std::mem::{self, MaybeUninit};
72+
use std::mem::{self, ManuallyDrop, MaybeUninit};
73+
use std::ops::DerefMut;
7374
use std::pin::{Pin, pin};
7475
use std::ptr::{self, NonNull};
7576
use 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

Comments
 (0)