I am struggling to understand the Host trait requirements when using wasmtime::component::bindgen! and linking wasm component imports.
I have a world which imports wasi:io so that I can use input-stream for communicating with the component. input-stream requires wasi:io/poll, wasi:io/streams, and wasi:io/error. I've included the .wit files for those in my wit folder. Everything works well until I try to add my imports to the linker with World::add_to_linker.
When I call add_to_linker, I receive errors like the trait bound MyState: wasmtime_wasi::p2::bindings::io::error::Host is not satisfied. I have figured out a work around that requires a few things that seem odd based on the examples and documentation I've read. The work around involves:
WorldImports for ResourceTable&mut to the ResourceTable of MyState in the closure passed to the add_to_linker callwith in the bindgen! call and providing import paths for wasi:io/poll, wasi:io/streams, and wasi:io/errorlinker.allow_shadowing(true)My questions are:
impl WorldImports on ResourceTable rather than MyState like I see in other examples? And why do I have to return a &mut to the ResourceTable in my add_to_linker closure rather than a &mut to MyState like I see in other examples?wasi:io/poll, wasi:io/streams, and wasi:io/error without having them defined twice in the linker? I call wasmtime_wasi::p2::add_to_linker_async(&mut linker)?; to satisfy the wasm interfaces. When coupled with the use of with in bindgen!, it results in them being defined twice. But if I don't use with in bindgen!, I don't get the implementation on the rust side.Hello! I think you're running into a similar issue as this thread -- -- where you have WIT bits but you kind of want to skip them in the generated add_to_linker. Right now that's not implemented but having such an implementation seems reasonable to me.
Okay. Any tips for understanding what the Host impls are actually doing? I can kind of understand the guest side, but figuring out what the Store and Linker are actually doing in order to satisfy lifetime and trait requirements is overwhelming me. I’d like to get to a point where I can implement my own stream to pass into a guest instead of using DuplexStream from tokio if that helps narrow the scope at all.
my suggestion, as the author of wasmtime-wasi-io, is to read the source of that crate and then see if you can use it for your purposes
AsyncReadStream and AsyncWriteStream from https://docs.rs/wasmtime-wasi/latest/wasmtime_wasi/p2/pipe/index.html may also be useful https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi/src/p2/pipe.rs
Last updated: Dec 06 2025 at 06:05 UTC