AmitPr opened issue #11287:
Hey folks, I was wondering whether I'm approaching this wrong, or whether this is an oversight in how
wasmtime::component::bindgen!works:I'm trying to write a WIT interface that allows me to return
wasi:keyvaluebuckets. Specifically:package amitpr:test interface root-store { use store.{bucket, error}; /// Open the root KV store open-root: func(identifier: string) -> result<bucket, error>; } world sudo { import root-store; }I then bindgen something like this:
wasmtime::component::bindgen!({ path: "wit", world: "amitpr:test/sudo", trappable_imports: true, with: { "wasi:keyvalue/store/bucket": crate::kv::bucket::MyBucket, }, trappable_error_type: { "wasi:keyvalue/store/error" => crate::kv::KVError, }, });The important thing to note, is that I already have
wasi:keyvalueimplemented elsewhere, which useswasi:keyvalue/importsand implements theHosttrait for those worlds.However, when I want to create a
Hostimplementation for thissudoworld, my struct is required to besudo::root_store::Host_as well as_wasi::keyvalue::store::Host:struct KvLibrary; impl HasData for KvLibrary { type Data<'a> = KvView<'a>; } struct SudoLibrary; impl HasData for SudoLibrary { type Data<'a> = SudoView<'a>; } // Later: // This works: kv::store::add_to_linker::<_, KvLibrary>(&mut linker, kv_getter)?; kv::atomics::add_to_linker::<_, KvLibrary>(&mut linker, kv_getter)?; kv::batch::add_to_linker::<_, KvLibrary>(&mut linker, kv_getter)?; // This tells me that SudoLibrary needs to implement keyvalue Host! sudo::add_to_linker::<_, SudoLibrary>(&mut linker, sudo_getter)?;I'm not 100% sure in what to do in this situation. Of course, I could duplicate the
wasi:keyvaluehost trait implementation, but that seems super unidiomatic. Am I missing why mySudoLibraryis enforced to implement thewasi:keyvalueworlds? Is there a way for me to invoke the macro without that bound, sincewasi:keyvaluewill already have bindings in my instantiation of the linker? Or is there a way for me to more idiomatically include thewasi:keyvaluehost implementation in theSudoViewstruct I have?Thanks
pchickey commented on issue #11287:
I believe this can be fixed if the sudo world's
withclause contains a mapping for the entire wasi:keyvalue/store interface to the generated bindings module for that interface, in addition to providing a mapping for the resource. You may be able to elide the mapping for the resource, but I'm not certain.
alexcrichton commented on issue #11287:
You might also need to use the per-interface
add_to_linkerinstead of a top-leveladd_to_linkerif you're using different data/projections for each of the*_getterfunctions.
alexcrichton added the wasmtime:api label to Issue #11287.
alexcrichton added the wasm-proposal:component-model label to Issue #11287.
AmitPr commented on issue #11287:
@pchickey this worked, but specifying the entire interface to another set of bindings seems like a somewhat flimsy way to set things up.
Not sure if this can be improved, to allow for the situation where there may be bindings in e.g. private modules. Perhaps this is addressed by eliding the mapping? Although I'm not sure how you would accomplish that.
Leaving this open, but feel free to close if status quo is alright
pchickey commented on issue #11287:
Sorry, I didn't elaborate much. This should only take a single line in
withpointing to a public module in another crate.The module with reusable bindings has to be public to be used from another crate, I don't think theres any way to get around that).
From my own project (sorry, no source link available at this time) which uses the wasmtime-wasi-io crate to implement wasi:io, and provides its own impls of the rest of the wasi interfaces (or any other wits which use any aspect of wasi:io):
wasmtime::component::bindgen!({ world: "my:embedding/bindings", exports: { default: async, }, imports: { default: trappable, }, with: { // delegate wasi-io implementation to wasmtime-wasi-io: "wasi:io": wasmtime_wasi_io::bindings::wasi::io, // Then, the rest of the definitions which are local to this crate: "wasi:http/types/incoming-request": http::IncomingRequestResource, // ...snip }, // This flag is required for compatibility with wasmtime-wasi-io: require_store_data_send: true, });
pchickey edited a comment on issue #11287:
Sorry, I didn't elaborate much. This should only take a single line in
withpointing to a public module in another crate.The module with reusable bindings has to be public to be used from another crate, I don't think theres any way to get around that).
From my own project (sorry, no source link available at this time) which uses the wasmtime-wasi-io crate to implement wasi:io, and provides its own impls of the rest of the wasi interfaces (or any other wits which use any aspect of wasi:io):
wasmtime::component::bindgen!({ world: "my:embedding/bindings", exports: { default: async, }, imports: { default: trappable, }, with: { // delegate wasi-io implementation to wasmtime-wasi-io: "wasi:io": wasmtime_wasi_io::bindings::wasi::io, // Then, the rest of the definitions which are local to this crate: "wasi:http/types/incoming-request": http::IncomingRequestResource, // ...snip }, // This flag is required for compatibility with wasmtime-wasi-io: require_store_data_send: true, });Does this technique feel less flimsy than what you did?
pchickey edited a comment on issue #11287:
Sorry, I didn't elaborate much. This should only take a single line in
withpointing to a public module in another crate.The module with reusable bindings has to be public to be used from another crate, I don't think theres any way to get around that.
From my own project (sorry, no source link available at this time) which uses the wasmtime-wasi-io crate to implement wasi:io, and provides its own impls of the rest of the wasi interfaces (or any other wits which use any aspect of wasi:io):
wasmtime::component::bindgen!({ world: "my:embedding/bindings", exports: { default: async, }, imports: { default: trappable, }, with: { // delegate wasi-io implementation to wasmtime-wasi-io: "wasi:io": wasmtime_wasi_io::bindings::wasi::io, // Then, the rest of the definitions which are local to this crate: "wasi:http/types/incoming-request": http::IncomingRequestResource, // ...snip }, // This flag is required for compatibility with wasmtime-wasi-io: require_store_data_send: true, });Does this technique feel less flimsy than what you did?
AmitPr closed issue #11287:
Hey folks, I was wondering whether I'm approaching this wrong, or whether this is an oversight in how
wasmtime::component::bindgen!works:I'm trying to write a WIT interface that allows me to return
wasi:keyvaluebuckets. Specifically:package amitpr:test interface root-store { use store.{bucket, error}; /// Open the root KV store open-root: func(identifier: string) -> result<bucket, error>; } world sudo { import root-store; }I then bindgen something like this:
wasmtime::component::bindgen!({ path: "wit", world: "amitpr:test/sudo", trappable_imports: true, with: { "wasi:keyvalue/store/bucket": crate::kv::bucket::MyBucket, }, trappable_error_type: { "wasi:keyvalue/store/error" => crate::kv::KVError, }, });The important thing to note, is that I already have
wasi:keyvalueimplemented elsewhere, which useswasi:keyvalue/importsand implements theHosttrait for those worlds.However, when I want to create a
Hostimplementation for thissudoworld, my struct is required to besudo::root_store::Host_as well as_wasi::keyvalue::store::Host:struct KvLibrary; impl HasData for KvLibrary { type Data<'a> = KvView<'a>; } struct SudoLibrary; impl HasData for SudoLibrary { type Data<'a> = SudoView<'a>; } // Later: // This works: kv::store::add_to_linker::<_, KvLibrary>(&mut linker, kv_getter)?; kv::atomics::add_to_linker::<_, KvLibrary>(&mut linker, kv_getter)?; kv::batch::add_to_linker::<_, KvLibrary>(&mut linker, kv_getter)?; // This tells me that SudoLibrary needs to implement keyvalue Host! sudo::add_to_linker::<_, SudoLibrary>(&mut linker, sudo_getter)?;I'm not 100% sure in what to do in this situation. Of course, I could duplicate the
wasi:keyvaluehost trait implementation, but that seems super unidiomatic. Am I missing why mySudoLibraryis enforced to implement thewasi:keyvalueworlds? Is there a way for me to invoke the macro without that bound, sincewasi:keyvaluewill already have bindings in my instantiation of the linker? Or is there a way for me to more idiomatically include thewasi:keyvaluehost implementation in theSudoViewstruct I have?Thanks
AmitPr commented on issue #11287:
Going to go ahead and close this; I think @pchickey’s technique works well and doesn’t feel much like a hack anymore!
Thanks folks
Last updated: Dec 06 2025 at 06:05 UTC