anlavandier opened issue #11752:
Test Case
Wit file:
package example:example; interface api { foo: func(); } world bar { import api; export baz: func(); } world api-impl { import api; }rust code:
use wasmtime::component::bindgen; use crate::async_impl::MyHost; bindgen!({ world: "bar", path: "wit/example.wit", with: { "example:example/api": async_impl, }, imports: { default: async, } }); pub mod async_impl { use wasmtime::component::bindgen; bindgen!({ world: "api-impl", path: "wit/example.wit", imports: { default: async, } }); pub struct MyHost; pub use example::example::api::{Host, HostWithStore, add_to_linker}; impl Host for MyHost { async fn foo(&mut self) { let _ = 3 + 4; } } } fn main() {}Expected results
The above code should compile
Observed results
the following compile error:
error[E0277]: `T` cannot be sent between threads safely --> src/main.rs:3:1 | 3 | / bindgen!({ 4 | | world: "bar", 5 | | path: "wit/example.wit", 6 | | with: { ... | 12 | | }); | |__^ `T` cannot be sent between threads safely | note: required by a bound in `add_to_linker` --> src/main.rs:16:5 | 16 | / bindgen!({ 17 | | world: "api-impl", 18 | | path: "wit/example.wit", 19 | | imports: { ... | 22 | | }); | |______^ required by this bound in `add_to_linker` = note: this error originates in the macro `bindgen` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `T` with trait `Send` | 12 | }), T: std::marker::Send; | ++++++++++++++++++++++Wasmtime version or commit:
wasmtime = { version ="37.0.1", default-features = false, features = ["runtime", "component-model", "async", "std"] }Operating system: N/A
Architecture: N/A
Extra info
Adding
import foobar: func();to thebarworld and adding a corresponding implementation ofBarImportsforMyHostfixes this.I believe that the bug is cause by the fact that
wit_bindgen::Generator::generate_add_to_linkerrelies on the presence of anasyncHosttrait for the target world (herebar). Because the world doesn't directly import anything and relies on interfaces implemented elsewhere, noHosttrait is generated and theFunctionFlags::ASYNCcan't be found. Here the relevant codePotential fix
I imagine that a way to fix this would be to really on
imports: {default: async}instead of theHosttrait. This would introduce a (in my head) minor inconvenience which is that code that declaresimports: {default: async}without actually needing it (because all of the interfaces that they import don't useasyncand they don't declare any "local" imports) will end up with an extraneousSendbounds but that feels like bad coding on the authors part and should not be supported imo.
anlavandier added the bug label to Issue #11752.
anlavandier edited issue #11752:
Test Case
Wit file:
package example:example; interface api { foo: func(); } world bar { import api; export baz: func(); } world api-impl { import api; }rust code:
use wasmtime::component::bindgen; use crate::async_impl::MyHost; bindgen!({ world: "bar", path: "wit/example.wit", with: { "example:example/api": async_impl, }, imports: { default: async, } }); pub mod async_impl { use wasmtime::component::bindgen; bindgen!({ world: "api-impl", path: "wit/example.wit", imports: { default: async, } }); pub struct MyHost; pub use example::example::api::{Host, HostWithStore, add_to_linker}; impl Host for MyHost { async fn foo(&mut self) { let _ = 3 + 4; } } } fn main() {}Expected results
The above code should compile
Observed results
the following compile error:
error[E0277]: `T` cannot be sent between threads safely --> src/main.rs:3:1 | 3 | / bindgen!({ 4 | | world: "bar", 5 | | path: "wit/example.wit", 6 | | with: { ... | 12 | | }); | |__^ `T` cannot be sent between threads safely | note: required by a bound in `add_to_linker` --> src/main.rs:16:5 | 16 | / bindgen!({ 17 | | world: "api-impl", 18 | | path: "wit/example.wit", 19 | | imports: { ... | 22 | | }); | |______^ required by this bound in `add_to_linker` = note: this error originates in the macro `bindgen` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `T` with trait `Send` | 12 | }), T: std::marker::Send; | ++++++++++++++++++++++Wasmtime version or commit:
wasmtime = { version ="37.0.1", default-features = false, features = ["runtime", "component-model", "async", "std"] }Operating system: N/A
Architecture: N/A
Extra info
Adding
import foobar: func();to thebarworld and adding a corresponding implementation ofBarImportsforMyHostfixes this.
I believe that the bug is cause by the fact thatwit_bindgen::wasmtime::world_add_to_linkerrelies on the presence of anasyncHosttrait for the target world (herebar). Because the world doesn't directly import anything and relies on interfaces implemented elsewhere, noHosttrait is generated and theFunctionFlags::ASYNCcan't be found. Here the relevant codeEdit: I should have tested my theories before writing them in the issue. I had misread the provenance of the code. I believe that my solution is still right so I'm keeping the section as is
Potential fix
I imagine that a way to fix this would be to really on
imports: {default: async}instead of theHosttrait. This would introduce a (in my head) minor inconvenience which is that code that declaresimports: {default: async}without actually needing it (because all of the interfaces that they import don't useasyncand they don't declare any "local" imports) will end up with an extraneousSendbounds but that feels like bad coding on the authors part and should not be supported imo.
anlavandier commented on issue #11752:
Interestingly, specifying the
asyncimport withimports: { "example:example/api": async, }leads to this error:rror: unused `imports` rules found: ["\"example:example/api\": FunctionFlags(ASYNC)"] --> src/main.rs:5:1 | 5 | / bindgen!({ 6 | | world: "bar", 7 | | path: "wit/example.wit", 8 | | with: { ... | 14 | | }); | |__^ | = note: this error originates in the macro `bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)
Last updated: Dec 06 2025 at 06:05 UTC