Skip to content

Commit 7c9d947

Browse files
committed
Add Send/Sync bounds to ComponentType
This commit is extracted from from review of bytecodealliance#11123 and bytecodealliance#11127. While not literally present in those PRs it's my own personal conclusion that it's best to just go ahead and add these bounds at the "base" of the component trait hierarchy. The current implementation in bytecodealliance#11123 adds bounds in many locations and this would remove the need to add bounds everywhere and instead have everything inherited through the `Lift` and `Lower` traits. This raises the question of: why? The main conclusion that I've reached leading to this change is that Wasmtime currently will store `R`, a return value, on the stack during the lowering process back into linear memory. This might involve allocation, however, meaning that wasm can be invoked and a context switch could happen. For Wasmtime's `unsafe impl` of `Send` and `Sync` on fibers to be sound it requires that this stack-local variable is also `Send` and `Sync` as it's an entirely user-provided type. Thus I've concluded that for results it's always required for these to be both `Send` and `Sync` (or at the very least, `Send`). Given that I've gone ahead and updated to require both `Send` and `Sync` for both params and results. This is not expected to actually have any impact in practice since all primitives are already `Send`/`Sync` (minus `Rc` impls all removed here) and all `bindgen!`-generated types are compositions of `Send`/`Sync` primitives meaning that they're also `Send` and `Sync`.
1 parent 6f999e1 commit 7c9d947

File tree

2 files changed

+26
-12
lines changed
  • crates/wasmtime/src/runtime/component/func
  • tests/all/component_model

2 files changed

+26
-12
lines changed

crates/wasmtime/src/runtime/component/func/typed.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ pub unsafe trait ComponentNamedList: ComponentType {}
678678
/// [d-cm]: macro@crate::component::ComponentType
679679
/// [f-m]: crate::component::flags
680680
///
681-
/// Rust standard library pointers such as `&T`, `Box<T>`, `Rc<T>`, and `Arc<T>`
681+
/// Rust standard library pointers such as `&T`, `Box<T>`, and `Arc<T>`
682682
/// additionally represent whatever type `T` represents in the component model.
683683
/// Note that types such as `record`, `variant`, `enum`, and `flags` are
684684
/// generated by the embedder at compile time. These macros derive
@@ -720,7 +720,29 @@ pub unsafe trait ComponentNamedList: ComponentType {}
720720
// Also note that this trait specifically is not sealed because we have a proc
721721
// macro that generates implementations of this trait for external types in a
722722
// `#[derive]`-like fashion.
723-
pub unsafe trait ComponentType {
723+
//
724+
// # Send and Sync
725+
//
726+
// While on the topic of safety it's worth discussing the `Send` and `Sync`
727+
// bounds here as well. These bounds might naively seem like they shouldn't be
728+
// required for all component types as they're host-level types not guest-level
729+
// types persisted anywhere. Various subtleties lead to these bounds, however:
730+
//
731+
// * Fibers require that all stack-local variables are `Send` and `Sync` for
732+
// fibers themselves to be send/sync. Unfortunately we have no help from the
733+
// compiler on this one so it's up to Wasmtime's discipline to maintain this.
734+
// One instance of this is that return values are placed on the stack as
735+
// they're lowered into guest memory. This lowering operation can involve
736+
// malloc and context switches, so return values must be Send/Sync.
737+
//
738+
// * In the implementation of component model async it's not uncommon for types
739+
// to be "buffered" in the store temporarily. For example parameters might
740+
// reside in a store temporarily while wasm has backpressure turned on.
741+
//
742+
// Overall it's generally easiest to require `Send` and `Sync` for all
743+
// component types. There additionally aren't known use case for non-`Send` or
744+
// non-`Sync` types at this time.
745+
pub unsafe trait ComponentType: Send + Sync {
724746
/// Representation of the "lowered" form of this component value.
725747
///
726748
/// Lowerings lower into core wasm values which are represented by `ValRaw`.
@@ -985,7 +1007,6 @@ macro_rules! forward_type_impls {
9851007
forward_type_impls! {
9861008
(T: ComponentType + ?Sized) &'_ T => T,
9871009
(T: ComponentType + ?Sized) Box<T> => T,
988-
(T: ComponentType + ?Sized) alloc::rc::Rc<T> => T,
9891010
(T: ComponentType + ?Sized) alloc::sync::Arc<T> => T,
9901011
() String => str,
9911012
(T: ComponentType) Vec<T> => [T],
@@ -1018,7 +1039,6 @@ macro_rules! forward_lowers {
10181039
forward_lowers! {
10191040
(T: Lower + ?Sized) &'_ T => T,
10201041
(T: Lower + ?Sized) Box<T> => T,
1021-
(T: Lower + ?Sized) alloc::rc::Rc<T> => T,
10221042
(T: Lower + ?Sized) alloc::sync::Arc<T> => T,
10231043
() String => str,
10241044
(T: Lower) Vec<T> => [T],
@@ -1042,7 +1062,6 @@ macro_rules! forward_string_lifts {
10421062

10431063
forward_string_lifts! {
10441064
Box<str>,
1045-
alloc::rc::Rc<str>,
10461065
alloc::sync::Arc<str>,
10471066
String,
10481067
}
@@ -1065,7 +1084,6 @@ macro_rules! forward_list_lifts {
10651084

10661085
forward_list_lifts! {
10671086
Box<[T]>,
1068-
alloc::rc::Rc<[T]>,
10691087
alloc::sync::Arc<[T]>,
10701088
Vec<T>,
10711089
}

tests/all/component_model/func.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
use super::{REALLOC_AND_FREE, TypedFuncExt};
44
use anyhow::Result;
5-
use std::rc::Rc;
65
use std::sync::Arc;
76
use wasmtime::component::*;
87
use wasmtime::{Engine, Store, StoreContextMut, Trap};
@@ -426,15 +425,12 @@ fn type_layers() -> Result<()> {
426425
instance
427426
.get_typed_func::<(&u32,), ()>(&mut store, "take-u32")?
428427
.call_and_post_return(&mut store, (&2,))?;
429-
instance
430-
.get_typed_func::<(Rc<u32>,), ()>(&mut store, "take-u32")?
431-
.call_and_post_return(&mut store, (Rc::new(2),))?;
432428
instance
433429
.get_typed_func::<(Arc<u32>,), ()>(&mut store, "take-u32")?
434430
.call_and_post_return(&mut store, (Arc::new(2),))?;
435431
instance
436-
.get_typed_func::<(&Box<Arc<Rc<u32>>>,), ()>(&mut store, "take-u32")?
437-
.call_and_post_return(&mut store, (&Box::new(Arc::new(Rc::new(2))),))?;
432+
.get_typed_func::<(&Box<Arc<Box<u32>>>,), ()>(&mut store, "take-u32")?
433+
.call_and_post_return(&mut store, (&Box::new(Arc::new(Box::new(2))),))?;
438434

439435
Ok(())
440436
}

0 commit comments

Comments
 (0)