diff --git a/Cargo.lock b/Cargo.lock index 81b69a03056d..8dfad6436a54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3849,7 +3849,7 @@ version = "0.14.0+wasi-0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d67b0bdfec72b9fbaba698033291c327ef19ce3b34efbdcd7dc402a53850d9" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen-rt 0.37.0", ] [[package]] @@ -3960,9 +3960,9 @@ checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "wasm-encoder" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e636076193fa68103e937ac951b5f2f587624097017d764b8984d9c0f149464" +checksum = "b7249cf8cb0c6b9cb42bce90c0a5feb276fbf963fa385ff3d818ab3d90818ed6" dependencies = [ "leb128", "wasmparser", @@ -3970,9 +3970,9 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c730c3379d3d20e5a0245b0724b924483e853588ca8fba547c1e21f19e7d735" +checksum = "79d13d93febc749413cb6f327e4fdba8c84e4d03bd69fcc4a220c66f113c8de1" dependencies = [ "anyhow", "indexmap 2.7.0", @@ -3987,9 +3987,9 @@ dependencies = [ [[package]] name = "wasm-mutate" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1ebeb8f91eda0710e5d556927696d06e1b8cc806bdffb0b8a44889ff54a77c" +checksum = "1d0ede8b5d000e2ea09926ae5c4783fa1503f779c3f5132a8c8b791121fe5a99" dependencies = [ "egg", "log", @@ -4001,9 +4001,9 @@ dependencies = [ [[package]] name = "wasm-smith" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ccae1e6cf6af813ea27efc5230a6db78260b5acfb2d4339b0300669bd213de0" +checksum = "d1c7826d83ef9b83db810c0b8442093cf51e726bf1ed3a75448617c5718fcc79" dependencies = [ "anyhow", "arbitrary", @@ -4023,9 +4023,9 @@ dependencies = [ [[package]] name = "wasm-wave" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d9362c422fad4e55376dbc937432bada2a9e4f4e3a6cbbc65363fa3323f897b" +checksum = "598c5e8b9f70d086d121e47153c44e35a5528e766eb817e4bb9dcacb8804c1be" dependencies = [ "indexmap 2.7.0", "logos", @@ -4079,9 +4079,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5a99faceb1a5a84dd6084ec4bfa4b2ab153b5793b43fd8f58b89232634afc35" +checksum = "65881a664fdd43646b647bb27bf186ab09c05bf56779d40aed4c6dce47d423f5" dependencies = [ "bitflags 2.6.0", "hashbrown 0.15.2", @@ -4101,9 +4101,9 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9235722b8cdb6c1c6daa537d4be4e230e76ce3ce0e4ba991956a1c6aed50305a" +checksum = "bc039e211f6c2137425726f0d76fdd9c439a442e5272bc3627a19274d0eb9686" dependencies = [ "anyhow", "termcolor", @@ -4123,6 +4123,7 @@ dependencies = [ "cfg-if", "encoding_rs", "env_logger 0.11.5", + "futures", "fxprof-processed-profile", "gimli", "hashbrown 0.15.2", @@ -4316,7 +4317,7 @@ dependencies = [ "wasmtime-wasi-threads", "wasmtime-wast", "wasmtime-wast-util", - "wast 223.0.0", + "wast 224.0.0", "wat", "windows-sys 0.59.0", "wit-component", @@ -4683,7 +4684,7 @@ dependencies = [ "anyhow", "log", "wasmtime", - "wast 223.0.0", + "wast 224.0.0", ] [[package]] @@ -4736,9 +4737,9 @@ dependencies = [ [[package]] name = "wast" -version = "223.0.0" +version = "224.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59b2ba8a2ff9f06194b7be9524f92e45e70149f4dacc0d0c7ad92b59ac875e4" +checksum = "d722a51e62b669d17e5a9f6bc8ec210178b37d869114355aa46989686c5c6391" dependencies = [ "bumpalo", "leb128", @@ -4749,11 +4750,11 @@ dependencies = [ [[package]] name = "wat" -version = "1.223.0" +version = "1.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662786915c427e4918ff01eabb3c4756d4d947cd8f635761526b4cc9da2eaaad" +checksum = "71dece6a7dd5bcbcf8d256606c7fb3faa36286d46bf3f98185407719a5ceede2" dependencies = [ - "wast 223.0.0", + "wast 224.0.0", ] [[package]] @@ -5118,19 +5119,19 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9219694564701fa935754f1552ce299154fc74948d6d148134ce55f3504c8bf1" +checksum = "b550e454e4cce8984398539a94a0226511e1f295b14afdc8f08b4e2e2ff9de3a" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen-rt 0.38.0", "wit-bindgen-rust-macro", ] [[package]] name = "wit-bindgen-core" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba105733ba146c94e067793fb46505265ea8720eb14ceae65b10797c7728a65" +checksum = "70e2f98d49960a416074c5d72889f810ed3032a32ffef5e4760094426fefbfe8" dependencies = [ "anyhow", "heck 0.5.0", @@ -5142,6 +5143,15 @@ name = "wit-bindgen-rt" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc801b991c56492f87ab3086e786468f75c285a4d73017ab0ebc2fa1aed5d82c" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6f8d372a2d4a1227f2556e051cc24b2a5f15768d53451c84ff91e2527139e3" dependencies = [ "bitflags 2.6.0", "futures", @@ -5150,9 +5160,9 @@ dependencies = [ [[package]] name = "wit-bindgen-rust" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257e0d217bc06635837d751447c39e77b9901752e052288ff6fe0fdb17850bc5" +checksum = "1cc49091f84e4f2ace078bbc86082b57e667b9e789baece4b1184e0963382b6e" dependencies = [ "anyhow", "heck 0.5.0", @@ -5166,9 +5176,9 @@ dependencies = [ [[package]] name = "wit-bindgen-rust-macro" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ac98caa9302234687b8e67ce7dfcf31ae5238523f166b93c23988fd0d4e0594" +checksum = "3545a699dc9d72298b2064ce71b771fc10fc6b757d29306b1e54a4283a75abba" dependencies = [ "anyhow", "prettyplease", @@ -5181,9 +5191,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10ed2aeee4c8ec5715875f62f4a3de3608d6987165c116810d8c2908aa9d93b" +checksum = "ad555ab4f4e676474df746d937823c7279c2d6dd36c3e97a61db893d4ef64ee5" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -5200,9 +5210,9 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.223.0" +version = "0.224.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92772f4dcacb804b275981eea1d920b12b377993b53307f1e33d87404e080281" +checksum = "23e2925a7365d2c6709ae17bdbb5777ffd8154fd70906b413fc01b75f0dba59e" dependencies = [ "anyhow", "id-arena", diff --git a/Cargo.toml b/Cargo.toml index 87c750ab8e2c..5b59df6b36ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -294,20 +294,20 @@ io-lifetimes = { version = "2.0.3", default-features = false } io-extras = "0.18.1" rustix = "0.38.43" # wit-bindgen: -wit-bindgen = { version = "0.37.0", default-features = false } -wit-bindgen-rust-macro = { version = "0.37.0", default-features = false } +wit-bindgen = { version = "0.38.0", default-features = false } +wit-bindgen-rust-macro = { version = "0.38.0", default-features = false } # wasm-tools family: -wasmparser = { version = "0.223.0", default-features = false, features = ['simd'] } -wat = "1.223.0" -wast = "223.0.0" -wasmprinter = "0.223.0" -wasm-encoder = "0.223.0" -wasm-smith = "0.223.0" -wasm-mutate = "0.223.0" -wit-parser = "0.223.0" -wit-component = "0.223.0" -wasm-wave = "0.223.0" +wasmparser = { version = "0.224.0", default-features = false, features = ['simd'] } +wat = "1.224.0" +wast = "224.0.0" +wasmprinter = "0.224.0" +wasm-encoder = "0.224.0" +wasm-smith = "0.224.0" +wasm-mutate = "0.224.0" +wit-parser = "0.224.0" +wit-component = "0.224.0" +wasm-wave = "0.224.0" # Non-Bytecode Alliance maintained dependencies: # -------------------------- diff --git a/crates/component-macro/Cargo.toml b/crates/component-macro/Cargo.toml index 79dbc6a27353..0d429aa080e2 100644 --- a/crates/component-macro/Cargo.toml +++ b/crates/component-macro/Cargo.toml @@ -29,7 +29,8 @@ wasmtime-wit-bindgen = { workspace = true } wit-parser = { workspace = true } [dev-dependencies] -wasmtime = { path = '../wasmtime', features = ['component-model'] } +wasmtime = { path = '../wasmtime', features = ['component-model', 'component-model-async'] } +wasmtime-wit-bindgen = { workspace = true, features = ['component-model-async'] } component-macro-test-helpers = { path = 'test-helpers' } tracing = { workspace = true } # For use with the custom attributes test @@ -41,3 +42,4 @@ similar = { workspace = true } [features] async = [] std = ['wasmtime-wit-bindgen/std'] +component-model-async = ['std', 'async', 'wasmtime-wit-bindgen/component-model-async'] diff --git a/crates/component-macro/src/bindgen.rs b/crates/component-macro/src/bindgen.rs index b33bbc5bcb7c..10b2c415bc15 100644 --- a/crates/component-macro/src/bindgen.rs +++ b/crates/component-macro/src/bindgen.rs @@ -1,14 +1,15 @@ use proc_macro2::{Span, TokenStream}; use quote::ToTokens; -use std::collections::HashMap; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::env; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; use syn::parse::{Error, Parse, ParseStream, Result}; use syn::punctuated::Punctuated; use syn::{braced, token, Token}; -use wasmtime_wit_bindgen::{AsyncConfig, Opts, Ownership, TrappableError, TrappableImports}; +use wasmtime_wit_bindgen::{ + AsyncConfig, CallStyle, Opts, Ownership, TrappableError, TrappableImports, +}; use wit_parser::{PackageId, Resolve, UnresolvedPackageGroup, WorldId}; pub struct Config { @@ -20,13 +21,22 @@ pub struct Config { } pub fn expand(input: &Config) -> Result { - if !cfg!(feature = "async") && input.opts.async_.maybe_async() { + if let (CallStyle::Async | CallStyle::Concurrent, false) = + (input.opts.call_style(), cfg!(feature = "async")) + { return Err(Error::new( Span::call_site(), "cannot enable async bindings unless `async` crate feature is active", )); } + if input.opts.concurrent_imports && !cfg!(feature = "component-model-async") { + return Err(Error::new( + Span::call_site(), + "cannot enable `concurrent_imports` option unless `component-model-async` crate feature is active", + )); + } + let mut src = match input.opts.generate(&input.resolve, input.world) { Ok(s) => s, Err(e) => return Err(Error::new(Span::call_site(), e.to_string())), @@ -40,7 +50,10 @@ pub fn expand(input: &Config) -> Result { // place a formatted version of the expanded code into a file. This file // will then show up in rustc error messages for any codegen issues and can // be inspected manually. - if input.include_generated_code_from_file || std::env::var("WASMTIME_DEBUG_BINDGEN").is_ok() { + if input.include_generated_code_from_file + || input.opts.debug + || std::env::var("WASMTIME_DEBUG_BINDGEN").is_ok() + { static INVOCATION: AtomicUsize = AtomicUsize::new(0); let root = Path::new(env!("DEBUG_OUTPUT_DIR")); let world_name = &input.resolve.worlds[input.world].name; @@ -107,6 +120,7 @@ impl Parse for Config { } Opt::Tracing(val) => opts.tracing = val, Opt::VerboseTracing(val) => opts.verbose_tracing = val, + Opt::Debug(val) => opts.debug = val, Opt::Async(val, span) => { if async_configured { return Err(Error::new(span, "cannot specify second async config")); @@ -114,6 +128,8 @@ impl Parse for Config { async_configured = true; opts.async_ = val; } + Opt::ConcurrentImports(val) => opts.concurrent_imports = val, + Opt::ConcurrentExports(val) => opts.concurrent_exports = val, Opt::TrappableErrorType(val) => opts.trappable_error_type = val, Opt::TrappableImports(val) => opts.trappable_imports = val, Opt::Ownership(val) => opts.ownership = val, @@ -138,7 +154,7 @@ impl Parse for Config { "cannot specify a world with `interfaces`", )); } - world = Some("interfaces".to_string()); + world = Some("wasmtime:component-macro-synthesized/interfaces".to_string()); opts.only_interfaces = true; } @@ -281,6 +297,9 @@ mod kw { syn::custom_keyword!(require_store_data_send); syn::custom_keyword!(wasmtime_crate); syn::custom_keyword!(include_generated_code_from_file); + syn::custom_keyword!(concurrent_imports); + syn::custom_keyword!(concurrent_exports); + syn::custom_keyword!(debug); } enum Opt { @@ -301,12 +320,19 @@ enum Opt { RequireStoreDataSend(bool), WasmtimeCrate(syn::Path), IncludeGeneratedCodeFromFile(bool), + ConcurrentImports(bool), + ConcurrentExports(bool), + Debug(bool), } impl Parse for Opt { fn parse(input: ParseStream<'_>) -> Result { let l = input.lookahead1(); - if l.peek(kw::path) { + if l.peek(kw::debug) { + input.parse::()?; + input.parse::()?; + Ok(Opt::Debug(input.parse::()?.value)) + } else if l.peek(kw::path) { input.parse::()?; input.parse::()?; @@ -380,6 +406,14 @@ impl Parse for Opt { span, )) } + } else if l.peek(kw::concurrent_imports) { + input.parse::()?; + input.parse::()?; + Ok(Opt::ConcurrentImports(input.parse::()?.value)) + } else if l.peek(kw::concurrent_exports) { + input.parse::()?; + input.parse::()?; + Ok(Opt::ConcurrentExports(input.parse::()?.value)) } else if l.peek(kw::ownership) { input.parse::()?; input.parse::()?; diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs index 73d61fd99539..0846ff8c7cf1 100644 --- a/crates/component-macro/tests/codegen.rs +++ b/crates/component-macro/tests/codegen.rs @@ -12,6 +12,14 @@ macro_rules! gentest { async: true, }); } + mod concurrent { + wasmtime::component::bindgen!({ + path: $path, + async: true, + concurrent_imports: true, + concurrent_exports: true, + }); + } mod tracing { wasmtime::component::bindgen!({ path: $path, diff --git a/crates/component-macro/tests/expanded.rs b/crates/component-macro/tests/expanded.rs index 29e338bc02f0..216e4cb47434 100644 --- a/crates/component-macro/tests/expanded.rs +++ b/crates/component-macro/tests/expanded.rs @@ -15,6 +15,14 @@ macro_rules! genexpand { stringify: true, }))?; + process_expanded($path, "_concurrent", wasmtime::component::bindgen!({ + path: $path, + async: true, + concurrent_imports: true, + concurrent_exports: true, + stringify: true, + }))?; + process_expanded($path, "_tracing_async", wasmtime::component::bindgen!({ path: $path, async: true, diff --git a/crates/component-macro/tests/expanded/char.rs b/crates/component-macro/tests/expanded/char.rs index 6ff749f08e7f..921b80f6812a 100644 --- a/crates/component-macro/tests/expanded/char.rs +++ b/crates/component-macro/tests/expanded/char.rs @@ -194,19 +194,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/chars")?; inst.func_wrap( @@ -354,7 +358,10 @@ pub mod exports { &self, mut store: S, arg0: char, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (char,), @@ -369,7 +376,10 @@ pub mod exports { pub fn call_return_char( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/char_async.rs b/crates/component-macro/tests/expanded/char_async.rs index 730c6acb3213..04fa8cc01223 100644 --- a/crates/component-macro/tests/expanded/char_async.rs +++ b/crates/component-macro/tests/expanded/char_async.rs @@ -202,19 +202,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/char_concurrent.rs b/crates/component-macro/tests/expanded/char_concurrent.rs new file mode 100644 index 000000000000..86581da05cf6 --- /dev/null +++ b/crates/component-macro/tests/expanded/char_concurrent.rs @@ -0,0 +1,492 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::chars::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::chars::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::chars::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::chars::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::chars::Host + 'static, + U: Send + foo::foo::chars::Host, + { + foo::foo::chars::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_chars(&self) -> &exports::foo::foo::chars::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod chars { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + /// A function that accepts a character + fn take_char( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: char, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + /// A function that returns a character + fn return_char( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> char + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/chars")?; + inst.func_wrap_concurrent( + "take-char", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (char,)| + { + let host = caller; + let r = ::take_char(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-char", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_char(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(char,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(char,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + /// A function that accepts a character + fn take_char( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: char, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::take_char(store, x) + } + /// A function that returns a character + fn return_char( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> char + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_char(store) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod chars { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + take_char: wasmtime::component::Func, + return_char: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + take_char: wasmtime::component::ComponentExportIndex, + return_char: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/chars") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/chars`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/chars") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/chars`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/chars` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let take_char = lookup("take-char")?; + let return_char = lookup("return-char")?; + Ok(GuestIndices { + take_char, + return_char, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let take_char = *_instance + .get_typed_func::<(char,), ()>(&mut store, &self.take_char)? + .func(); + let return_char = *_instance + .get_typed_func::< + (), + (char,), + >(&mut store, &self.return_char)? + .func(); + Ok(Guest { take_char, return_char }) + } + } + impl Guest { + /// A function that accepts a character + pub async fn call_take_char( + &self, + mut store: S, + arg0: char, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (char,), + (), + >::new_unchecked(self.take_char) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + /// A function that returns a character + pub async fn call_return_char( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (char,), + >::new_unchecked(self.return_char) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/char_tracing_async.rs b/crates/component-macro/tests/expanded/char_tracing_async.rs index aa1f926ea35f..ca8d823d8b27 100644 --- a/crates/component-macro/tests/expanded/char_tracing_async.rs +++ b/crates/component-macro/tests/expanded/char_tracing_async.rs @@ -202,19 +202,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/conventions.rs b/crates/component-macro/tests/expanded/conventions.rs index b808807a8140..c4d8e2f6b7ce 100644 --- a/crates/component-macro/tests/expanded/conventions.rs +++ b/crates/component-macro/tests/expanded/conventions.rs @@ -242,19 +242,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/conventions")?; inst.func_wrap( @@ -646,7 +650,10 @@ pub mod exports { pub fn call_kebab_case( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -661,7 +668,10 @@ pub mod exports { &self, mut store: S, arg0: LudicrousSpeed, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (LudicrousSpeed,), @@ -675,7 +685,10 @@ pub mod exports { pub fn call_function_with_dashes( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -688,7 +701,10 @@ pub mod exports { } pub fn call_function_with_no_weird_characters< S: wasmtime::AsContextMut, - >(&self, mut store: S) -> wasmtime::Result<()> { + >(&self, mut store: S) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -702,7 +718,10 @@ pub mod exports { pub fn call_apple( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -716,7 +735,10 @@ pub mod exports { pub fn call_apple_pear( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -730,7 +752,10 @@ pub mod exports { pub fn call_apple_pear_grape( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -744,7 +769,10 @@ pub mod exports { pub fn call_a0( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -763,7 +791,10 @@ pub mod exports { pub fn call_is_xml( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -777,7 +808,10 @@ pub mod exports { pub fn call_explicit( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -791,7 +825,10 @@ pub mod exports { pub fn call_explicit_kebab( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -806,7 +843,10 @@ pub mod exports { pub fn call_bool( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/conventions_async.rs b/crates/component-macro/tests/expanded/conventions_async.rs index 1e8f3bbd0693..8f8826e7e00e 100644 --- a/crates/component-macro/tests/expanded/conventions_async.rs +++ b/crates/component-macro/tests/expanded/conventions_async.rs @@ -250,19 +250,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/conventions_concurrent.rs b/crates/component-macro/tests/expanded/conventions_concurrent.rs new file mode 100644 index 000000000000..df541fb6827f --- /dev/null +++ b/crates/component-macro/tests/expanded/conventions_concurrent.rs @@ -0,0 +1,1364 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::conventions::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::conventions::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::conventions::GuestIndices::new( + _component, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::conventions::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::conventions::Host + 'static, + U: Send + foo::foo::conventions::Host, + { + foo::foo::conventions::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_conventions(&self) -> &exports::foo::foo::conventions::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod conventions { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct LudicrousSpeed { + #[component(name = "how-fast-are-you-going")] + pub how_fast_are_you_going: u32, + #[component(name = "i-am-going-extremely-slow")] + pub i_am_going_extremely_slow: u64, + } + impl core::fmt::Debug for LudicrousSpeed { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("LudicrousSpeed") + .field("how-fast-are-you-going", &self.how_fast_are_you_going) + .field( + "i-am-going-extremely-slow", + &self.i_am_going_extremely_slow, + ) + .finish() + } + } + const _: () = { + assert!( + 16 == < LudicrousSpeed as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 8 == < LudicrousSpeed as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub trait Host { + type Data; + fn kebab_case( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: LudicrousSpeed, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn function_with_dashes( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn function_with_no_weird_characters( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn apple( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn apple_pear( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn apple_pear_grape( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a0( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + /// Comment out identifiers that collide when mapped to snake_case, for now; see + /// https://github.com/WebAssembly/component-model/issues/118 + /// APPLE: func() + /// APPLE-pear-GRAPE: func() + /// apple-PEAR-grape: func() + fn is_xml( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn explicit( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn explicit_kebab( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + /// Identifiers with the same name as keywords are quoted. + fn bool( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/conventions")?; + inst.func_wrap_concurrent( + "kebab-case", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::kebab_case(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "foo", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (LudicrousSpeed,)| + { + let host = caller; + let r = ::foo(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "function-with-dashes", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::function_with_dashes(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "function-with-no-weird-characters", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::function_with_no_weird_characters( + host, + ); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "apple", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::apple(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "apple-pear", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::apple_pear(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "apple-pear-grape", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::apple_pear_grape(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a0", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::a0(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "is-XML", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::is_xml(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "explicit", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::explicit(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "explicit-kebab", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::explicit_kebab(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "bool", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::bool(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn kebab_case( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::kebab_case(store) + } + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: LudicrousSpeed, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::foo(store, x) + } + fn function_with_dashes( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::function_with_dashes(store) + } + fn function_with_no_weird_characters( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::function_with_no_weird_characters(store) + } + fn apple( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::apple(store) + } + fn apple_pear( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::apple_pear(store) + } + fn apple_pear_grape( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::apple_pear_grape(store) + } + fn a0( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a0(store) + } + /// Comment out identifiers that collide when mapped to snake_case, for now; see + /// https://github.com/WebAssembly/component-model/issues/118 + /// APPLE: func() + /// APPLE-pear-GRAPE: func() + /// apple-PEAR-grape: func() + fn is_xml( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::is_xml(store) + } + fn explicit( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::explicit(store) + } + fn explicit_kebab( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::explicit_kebab(store) + } + /// Identifiers with the same name as keywords are quoted. + fn bool( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::bool(store) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod conventions { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct LudicrousSpeed { + #[component(name = "how-fast-are-you-going")] + pub how_fast_are_you_going: u32, + #[component(name = "i-am-going-extremely-slow")] + pub i_am_going_extremely_slow: u64, + } + impl core::fmt::Debug for LudicrousSpeed { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("LudicrousSpeed") + .field( + "how-fast-are-you-going", + &self.how_fast_are_you_going, + ) + .field( + "i-am-going-extremely-slow", + &self.i_am_going_extremely_slow, + ) + .finish() + } + } + const _: () = { + assert!( + 16 == < LudicrousSpeed as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 8 == < LudicrousSpeed as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub struct Guest { + kebab_case: wasmtime::component::Func, + foo: wasmtime::component::Func, + function_with_dashes: wasmtime::component::Func, + function_with_no_weird_characters: wasmtime::component::Func, + apple: wasmtime::component::Func, + apple_pear: wasmtime::component::Func, + apple_pear_grape: wasmtime::component::Func, + a0: wasmtime::component::Func, + is_xml: wasmtime::component::Func, + explicit: wasmtime::component::Func, + explicit_kebab: wasmtime::component::Func, + bool: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + kebab_case: wasmtime::component::ComponentExportIndex, + foo: wasmtime::component::ComponentExportIndex, + function_with_dashes: wasmtime::component::ComponentExportIndex, + function_with_no_weird_characters: wasmtime::component::ComponentExportIndex, + apple: wasmtime::component::ComponentExportIndex, + apple_pear: wasmtime::component::ComponentExportIndex, + apple_pear_grape: wasmtime::component::ComponentExportIndex, + a0: wasmtime::component::ComponentExportIndex, + is_xml: wasmtime::component::ComponentExportIndex, + explicit: wasmtime::component::ComponentExportIndex, + explicit_kebab: wasmtime::component::ComponentExportIndex, + bool: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/conventions") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/conventions`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/conventions") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/conventions`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/conventions` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let kebab_case = lookup("kebab-case")?; + let foo = lookup("foo")?; + let function_with_dashes = lookup("function-with-dashes")?; + let function_with_no_weird_characters = lookup( + "function-with-no-weird-characters", + )?; + let apple = lookup("apple")?; + let apple_pear = lookup("apple-pear")?; + let apple_pear_grape = lookup("apple-pear-grape")?; + let a0 = lookup("a0")?; + let is_xml = lookup("is-XML")?; + let explicit = lookup("explicit")?; + let explicit_kebab = lookup("explicit-kebab")?; + let bool = lookup("bool")?; + Ok(GuestIndices { + kebab_case, + foo, + function_with_dashes, + function_with_no_weird_characters, + apple, + apple_pear, + apple_pear_grape, + a0, + is_xml, + explicit, + explicit_kebab, + bool, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let kebab_case = *_instance + .get_typed_func::<(), ()>(&mut store, &self.kebab_case)? + .func(); + let foo = *_instance + .get_typed_func::< + (LudicrousSpeed,), + (), + >(&mut store, &self.foo)? + .func(); + let function_with_dashes = *_instance + .get_typed_func::< + (), + (), + >(&mut store, &self.function_with_dashes)? + .func(); + let function_with_no_weird_characters = *_instance + .get_typed_func::< + (), + (), + >(&mut store, &self.function_with_no_weird_characters)? + .func(); + let apple = *_instance + .get_typed_func::<(), ()>(&mut store, &self.apple)? + .func(); + let apple_pear = *_instance + .get_typed_func::<(), ()>(&mut store, &self.apple_pear)? + .func(); + let apple_pear_grape = *_instance + .get_typed_func::< + (), + (), + >(&mut store, &self.apple_pear_grape)? + .func(); + let a0 = *_instance + .get_typed_func::<(), ()>(&mut store, &self.a0)? + .func(); + let is_xml = *_instance + .get_typed_func::<(), ()>(&mut store, &self.is_xml)? + .func(); + let explicit = *_instance + .get_typed_func::<(), ()>(&mut store, &self.explicit)? + .func(); + let explicit_kebab = *_instance + .get_typed_func::<(), ()>(&mut store, &self.explicit_kebab)? + .func(); + let bool = *_instance + .get_typed_func::<(), ()>(&mut store, &self.bool)? + .func(); + Ok(Guest { + kebab_case, + foo, + function_with_dashes, + function_with_no_weird_characters, + apple, + apple_pear, + apple_pear_grape, + a0, + is_xml, + explicit, + explicit_kebab, + bool, + }) + } + } + impl Guest { + pub async fn call_kebab_case( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.kebab_case) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_foo( + &self, + mut store: S, + arg0: LudicrousSpeed, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (LudicrousSpeed,), + (), + >::new_unchecked(self.foo) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_function_with_dashes( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.function_with_dashes) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_function_with_no_weird_characters< + S: wasmtime::AsContextMut, + >( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.function_with_no_weird_characters) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_apple( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.apple) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_apple_pear( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.apple_pear) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_apple_pear_grape( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.apple_pear_grape) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_a0( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.a0) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + /// Comment out identifiers that collide when mapped to snake_case, for now; see + /// https://github.com/WebAssembly/component-model/issues/118 + /// APPLE: func() + /// APPLE-pear-GRAPE: func() + /// apple-PEAR-grape: func() + pub async fn call_is_xml( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.is_xml) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_explicit( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.explicit) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_explicit_kebab( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.explicit_kebab) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + /// Identifiers with the same name as keywords are quoted. + pub async fn call_bool( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.bool) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/conventions_tracing_async.rs b/crates/component-macro/tests/expanded/conventions_tracing_async.rs index 011ca5b9f146..6dbe91e8e692 100644 --- a/crates/component-macro/tests/expanded/conventions_tracing_async.rs +++ b/crates/component-macro/tests/expanded/conventions_tracing_async.rs @@ -250,19 +250,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/dead-code.rs b/crates/component-macro/tests/expanded/dead-code.rs index 23f775721411..7c230eb56aad 100644 --- a/crates/component-macro/tests/expanded/dead-code.rs +++ b/crates/component-macro/tests/expanded/dead-code.rs @@ -200,19 +200,23 @@ pub mod a { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("a:b/interface-with-live-type")?; inst.func_wrap( @@ -247,19 +251,23 @@ pub mod a { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("a:b/interface-with-dead-type")?; Ok(()) diff --git a/crates/component-macro/tests/expanded/dead-code_async.rs b/crates/component-macro/tests/expanded/dead-code_async.rs index 7ba8b30a3908..5ae89b9a6196 100644 --- a/crates/component-macro/tests/expanded/dead-code_async.rs +++ b/crates/component-macro/tests/expanded/dead-code_async.rs @@ -208,19 +208,23 @@ pub mod a { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -262,19 +266,23 @@ pub mod a { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/dead-code_concurrent.rs b/crates/component-macro/tests/expanded/dead-code_concurrent.rs new file mode 100644 index 000000000000..839a439c6bc6 --- /dev/null +++ b/crates/component-macro/tests/expanded/dead-code_concurrent.rs @@ -0,0 +1,344 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `imports`. +/// +/// This structure is created through [`ImportsPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Imports`] as well. +pub struct ImportsPre { + instance_pre: wasmtime::component::InstancePre, + indices: ImportsIndices, +} +impl Clone for ImportsPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> ImportsPre<_T> { + /// Creates a new copy of `ImportsPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = ImportsIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Imports`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `imports`. +/// +/// This is an implementation detail of [`ImportsPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Imports`] as well. +#[derive(Clone)] +pub struct ImportsIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `imports`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Imports::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`ImportsPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`ImportsPre::instantiate_async`] to +/// create a [`Imports`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Imports::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`ImportsIndices::new_instance`] followed +/// by [`ImportsIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Imports {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl ImportsIndices { + /// Creates a new copy of `ImportsIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(ImportsIndices {}) + } + /// Creates a new instance of [`ImportsIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Imports`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Imports`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(ImportsIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Imports`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Imports {}) + } + } + impl Imports { + /// Convenience wrapper around [`ImportsPre::new`] and + /// [`ImportsPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + ImportsPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`ImportsIndices::new_instance`] and + /// [`ImportsIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = ImportsIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + a::b::interface_with_live_type::Host + + a::b::interface_with_dead_type::Host + 'static, + U: Send + a::b::interface_with_live_type::Host + + a::b::interface_with_dead_type::Host, + { + a::b::interface_with_live_type::add_to_linker(linker, get)?; + a::b::interface_with_dead_type::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +pub mod a { + pub mod b { + #[allow(clippy::all)] + pub mod interface_with_live_type { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct LiveType { + #[component(name = "a")] + pub a: u32, + } + impl core::fmt::Debug for LiveType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("LiveType").field("a", &self.a).finish() + } + } + const _: () = { + assert!(4 == < LiveType as wasmtime::component::ComponentType >::SIZE32); + assert!( + 4 == < LiveType as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub trait Host { + type Data; + fn f( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> LiveType + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("a:b/interface-with-live-type")?; + inst.func_wrap_concurrent( + "f", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::f(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(LiveType,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(LiveType,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn f( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> LiveType + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f(store) + } + } + } + #[allow(clippy::all)] + pub mod interface_with_dead_type { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("a:b/interface-with-dead-type")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} diff --git a/crates/component-macro/tests/expanded/dead-code_tracing_async.rs b/crates/component-macro/tests/expanded/dead-code_tracing_async.rs index b394499697c0..5261c71d5d8d 100644 --- a/crates/component-macro/tests/expanded/dead-code_tracing_async.rs +++ b/crates/component-macro/tests/expanded/dead-code_tracing_async.rs @@ -208,19 +208,23 @@ pub mod a { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -275,19 +279,23 @@ pub mod a { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/direct-import.rs b/crates/component-macro/tests/expanded/direct-import.rs index 225fe6c9009f..aa46750e55d5 100644 --- a/crates/component-macro/tests/expanded/direct-import.rs +++ b/crates/component-macro/tests/expanded/direct-import.rs @@ -97,10 +97,11 @@ pub trait FooImports { } pub trait FooImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: FooImports; } -impl FooImportsGetHost for F +impl FooImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: FooImports, @@ -175,9 +176,12 @@ const _: () = { let indices = FooIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> FooImportsGetHost<&'a mut T, T, Host: FooImports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> FooImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut linker = linker.root(); linker diff --git a/crates/component-macro/tests/expanded/direct-import_async.rs b/crates/component-macro/tests/expanded/direct-import_async.rs index a0ab29ebc481..cb94824920e3 100644 --- a/crates/component-macro/tests/expanded/direct-import_async.rs +++ b/crates/component-macro/tests/expanded/direct-import_async.rs @@ -101,10 +101,11 @@ pub trait FooImports: Send { } pub trait FooImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: FooImports; } -impl FooImportsGetHost for F +impl FooImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: FooImports, @@ -182,9 +183,12 @@ const _: () = { let indices = FooIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> FooImportsGetHost<&'a mut T, T, Host: FooImports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> FooImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/direct-import_concurrent.rs b/crates/component-macro/tests/expanded/direct-import_concurrent.rs new file mode 100644 index 000000000000..feb06fd9f4be --- /dev/null +++ b/crates/component-macro/tests/expanded/direct-import_concurrent.rs @@ -0,0 +1,260 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `foo`. +/// +/// This structure is created through [`FooPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Foo`] as well. +pub struct FooPre { + instance_pre: wasmtime::component::InstancePre, + indices: FooIndices, +} +impl Clone for FooPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> FooPre<_T> { + /// Creates a new copy of `FooPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = FooIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Foo`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `foo`. +/// +/// This is an implementation detail of [`FooPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Foo`] as well. +#[derive(Clone)] +pub struct FooIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `foo`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Foo::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`FooPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`FooPre::instantiate_async`] to +/// create a [`Foo`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Foo::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`FooIndices::new_instance`] followed +/// by [`FooIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Foo {} +pub trait FooImports { + type Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; +} +pub trait FooImportsGetHost< + T, + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: FooImports; +} +impl FooImportsGetHost for F +where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: FooImports, +{ + type Host = O; +} +impl<_T: FooImports> FooImports for &mut _T { + type Data = _T::Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as FooImports>::foo(store) + } +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl FooIndices { + /// Creates a new copy of `FooIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(FooIndices {}) + } + /// Creates a new instance of [`FooIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Foo`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Foo`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(FooIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Foo`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Foo {}) + } + } + impl Foo { + /// Convenience wrapper around [`FooPre::new`] and + /// [`FooPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + FooPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`FooIndices::new_instance`] and + /// [`FooIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = FooIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> FooImportsGetHost<&'a mut T, T, Host: FooImports>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut linker = linker.root(); + linker + .func_wrap_concurrent( + "foo", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::foo(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + FooImports + 'static, + U: Send + FooImports, + { + Self::add_to_linker_imports_get_host(linker, get)?; + Ok(()) + } + } +}; diff --git a/crates/component-macro/tests/expanded/direct-import_tracing_async.rs b/crates/component-macro/tests/expanded/direct-import_tracing_async.rs index 1ee124c08a94..fac78c56f736 100644 --- a/crates/component-macro/tests/expanded/direct-import_tracing_async.rs +++ b/crates/component-macro/tests/expanded/direct-import_tracing_async.rs @@ -101,10 +101,11 @@ pub trait FooImports: Send { } pub trait FooImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: FooImports; } -impl FooImportsGetHost for F +impl FooImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: FooImports, @@ -182,9 +183,12 @@ const _: () = { let indices = FooIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> FooImportsGetHost<&'a mut T, T, Host: FooImports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> FooImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/empty_concurrent.rs b/crates/component-macro/tests/expanded/empty_concurrent.rs new file mode 100644 index 000000000000..fd5817a596b0 --- /dev/null +++ b/crates/component-macro/tests/expanded/empty_concurrent.rs @@ -0,0 +1,165 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `empty`. +/// +/// This structure is created through [`EmptyPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Empty`] as well. +pub struct EmptyPre { + instance_pre: wasmtime::component::InstancePre, + indices: EmptyIndices, +} +impl Clone for EmptyPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> EmptyPre<_T> { + /// Creates a new copy of `EmptyPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = EmptyIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Empty`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `empty`. +/// +/// This is an implementation detail of [`EmptyPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Empty`] as well. +#[derive(Clone)] +pub struct EmptyIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `empty`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Empty::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`EmptyPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`EmptyPre::instantiate_async`] to +/// create a [`Empty`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Empty::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`EmptyIndices::new_instance`] followed +/// by [`EmptyIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Empty {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl EmptyIndices { + /// Creates a new copy of `EmptyIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(EmptyIndices {}) + } + /// Creates a new instance of [`EmptyIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Empty`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Empty`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(EmptyIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Empty`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Empty {}) + } + } + impl Empty { + /// Convenience wrapper around [`EmptyPre::new`] and + /// [`EmptyPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + EmptyPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`EmptyIndices::new_instance`] and + /// [`EmptyIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = EmptyIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + } +}; diff --git a/crates/component-macro/tests/expanded/flags.rs b/crates/component-macro/tests/expanded/flags.rs index 456c9a239905..a89525ca62f0 100644 --- a/crates/component-macro/tests/expanded/flags.rs +++ b/crates/component-macro/tests/expanded/flags.rs @@ -311,19 +311,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/flegs")?; inst.func_wrap( @@ -751,7 +755,10 @@ pub mod exports { &self, mut store: S, arg0: Flag1, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Flag1,), @@ -766,7 +773,10 @@ pub mod exports { &self, mut store: S, arg0: Flag2, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Flag2,), @@ -781,7 +791,10 @@ pub mod exports { &self, mut store: S, arg0: Flag4, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Flag4,), @@ -796,7 +809,10 @@ pub mod exports { &self, mut store: S, arg0: Flag8, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Flag8,), @@ -811,7 +827,10 @@ pub mod exports { &self, mut store: S, arg0: Flag16, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Flag16,), @@ -826,7 +845,10 @@ pub mod exports { &self, mut store: S, arg0: Flag32, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Flag32,), @@ -841,7 +863,10 @@ pub mod exports { &self, mut store: S, arg0: Flag64, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Flag64,), diff --git a/crates/component-macro/tests/expanded/flags_async.rs b/crates/component-macro/tests/expanded/flags_async.rs index c872a542d0ce..54c3f730eb16 100644 --- a/crates/component-macro/tests/expanded/flags_async.rs +++ b/crates/component-macro/tests/expanded/flags_async.rs @@ -319,19 +319,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/flags_concurrent.rs b/crates/component-macro/tests/expanded/flags_concurrent.rs new file mode 100644 index 000000000000..533676692911 --- /dev/null +++ b/crates/component-macro/tests/expanded/flags_concurrent.rs @@ -0,0 +1,1191 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-flags`. +/// +/// This structure is created through [`TheFlagsPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheFlags`] as well. +pub struct TheFlagsPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheFlagsIndices, +} +impl Clone for TheFlagsPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheFlagsPre<_T> { + /// Creates a new copy of `TheFlagsPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheFlagsIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheFlags`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-flags`. +/// +/// This is an implementation detail of [`TheFlagsPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheFlags`] as well. +#[derive(Clone)] +pub struct TheFlagsIndices { + interface0: exports::foo::foo::flegs::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-flags`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheFlags::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheFlagsPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheFlagsPre::instantiate_async`] to +/// create a [`TheFlags`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheFlags::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheFlagsIndices::new_instance`] followed +/// by [`TheFlagsIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheFlags { + interface0: exports::foo::foo::flegs::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheFlagsIndices { + /// Creates a new copy of `TheFlagsIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::flegs::GuestIndices::new(_component)?; + Ok(TheFlagsIndices { interface0 }) + } + /// Creates a new instance of [`TheFlagsIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheFlags`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheFlags`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::flegs::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheFlagsIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheFlags`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheFlags { interface0 }) + } + } + impl TheFlags { + /// Convenience wrapper around [`TheFlagsPre::new`] and + /// [`TheFlagsPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheFlagsPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheFlagsIndices::new_instance`] and + /// [`TheFlagsIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheFlagsIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::flegs::Host + 'static, + U: Send + foo::foo::flegs::Host, + { + foo::foo::flegs::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_flegs(&self) -> &exports::foo::foo::flegs::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod flegs { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + wasmtime::component::flags!(Flag1 { #[component(name = "b0")] const B0; }); + const _: () = { + assert!(1 == < Flag1 as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Flag1 as wasmtime::component::ComponentType >::ALIGN32); + }; + wasmtime::component::flags!( + Flag2 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; } + ); + const _: () = { + assert!(1 == < Flag2 as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Flag2 as wasmtime::component::ComponentType >::ALIGN32); + }; + wasmtime::component::flags!( + Flag4 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; #[component(name = "b2")] const B2; #[component(name = "b3")] + const B3; } + ); + const _: () = { + assert!(1 == < Flag4 as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Flag4 as wasmtime::component::ComponentType >::ALIGN32); + }; + wasmtime::component::flags!( + Flag8 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; #[component(name = "b2")] const B2; #[component(name = "b3")] + const B3; #[component(name = "b4")] const B4; #[component(name = "b5")] + const B5; #[component(name = "b6")] const B6; #[component(name = "b7")] + const B7; } + ); + const _: () = { + assert!(1 == < Flag8 as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Flag8 as wasmtime::component::ComponentType >::ALIGN32); + }; + wasmtime::component::flags!( + Flag16 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; #[component(name = "b2")] const B2; #[component(name = "b3")] + const B3; #[component(name = "b4")] const B4; #[component(name = "b5")] + const B5; #[component(name = "b6")] const B6; #[component(name = "b7")] + const B7; #[component(name = "b8")] const B8; #[component(name = "b9")] + const B9; #[component(name = "b10")] const B10; #[component(name = + "b11")] const B11; #[component(name = "b12")] const B12; #[component(name + = "b13")] const B13; #[component(name = "b14")] const B14; + #[component(name = "b15")] const B15; } + ); + const _: () = { + assert!(2 == < Flag16 as wasmtime::component::ComponentType >::SIZE32); + assert!(2 == < Flag16 as wasmtime::component::ComponentType >::ALIGN32); + }; + wasmtime::component::flags!( + Flag32 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; #[component(name = "b2")] const B2; #[component(name = "b3")] + const B3; #[component(name = "b4")] const B4; #[component(name = "b5")] + const B5; #[component(name = "b6")] const B6; #[component(name = "b7")] + const B7; #[component(name = "b8")] const B8; #[component(name = "b9")] + const B9; #[component(name = "b10")] const B10; #[component(name = + "b11")] const B11; #[component(name = "b12")] const B12; #[component(name + = "b13")] const B13; #[component(name = "b14")] const B14; + #[component(name = "b15")] const B15; #[component(name = "b16")] const + B16; #[component(name = "b17")] const B17; #[component(name = "b18")] + const B18; #[component(name = "b19")] const B19; #[component(name = + "b20")] const B20; #[component(name = "b21")] const B21; #[component(name + = "b22")] const B22; #[component(name = "b23")] const B23; + #[component(name = "b24")] const B24; #[component(name = "b25")] const + B25; #[component(name = "b26")] const B26; #[component(name = "b27")] + const B27; #[component(name = "b28")] const B28; #[component(name = + "b29")] const B29; #[component(name = "b30")] const B30; #[component(name + = "b31")] const B31; } + ); + const _: () = { + assert!(4 == < Flag32 as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Flag32 as wasmtime::component::ComponentType >::ALIGN32); + }; + wasmtime::component::flags!( + Flag64 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; #[component(name = "b2")] const B2; #[component(name = "b3")] + const B3; #[component(name = "b4")] const B4; #[component(name = "b5")] + const B5; #[component(name = "b6")] const B6; #[component(name = "b7")] + const B7; #[component(name = "b8")] const B8; #[component(name = "b9")] + const B9; #[component(name = "b10")] const B10; #[component(name = + "b11")] const B11; #[component(name = "b12")] const B12; #[component(name + = "b13")] const B13; #[component(name = "b14")] const B14; + #[component(name = "b15")] const B15; #[component(name = "b16")] const + B16; #[component(name = "b17")] const B17; #[component(name = "b18")] + const B18; #[component(name = "b19")] const B19; #[component(name = + "b20")] const B20; #[component(name = "b21")] const B21; #[component(name + = "b22")] const B22; #[component(name = "b23")] const B23; + #[component(name = "b24")] const B24; #[component(name = "b25")] const + B25; #[component(name = "b26")] const B26; #[component(name = "b27")] + const B27; #[component(name = "b28")] const B28; #[component(name = + "b29")] const B29; #[component(name = "b30")] const B30; #[component(name + = "b31")] const B31; #[component(name = "b32")] const B32; + #[component(name = "b33")] const B33; #[component(name = "b34")] const + B34; #[component(name = "b35")] const B35; #[component(name = "b36")] + const B36; #[component(name = "b37")] const B37; #[component(name = + "b38")] const B38; #[component(name = "b39")] const B39; #[component(name + = "b40")] const B40; #[component(name = "b41")] const B41; + #[component(name = "b42")] const B42; #[component(name = "b43")] const + B43; #[component(name = "b44")] const B44; #[component(name = "b45")] + const B45; #[component(name = "b46")] const B46; #[component(name = + "b47")] const B47; #[component(name = "b48")] const B48; #[component(name + = "b49")] const B49; #[component(name = "b50")] const B50; + #[component(name = "b51")] const B51; #[component(name = "b52")] const + B52; #[component(name = "b53")] const B53; #[component(name = "b54")] + const B54; #[component(name = "b55")] const B55; #[component(name = + "b56")] const B56; #[component(name = "b57")] const B57; #[component(name + = "b58")] const B58; #[component(name = "b59")] const B59; + #[component(name = "b60")] const B60; #[component(name = "b61")] const + B61; #[component(name = "b62")] const B62; #[component(name = "b63")] + const B63; } + ); + const _: () = { + assert!(8 == < Flag64 as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Flag64 as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn roundtrip_flag1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag1, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag1 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn roundtrip_flag2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag2, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag2 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn roundtrip_flag4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag4, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag4 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn roundtrip_flag8( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag8, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag8 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn roundtrip_flag16( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag16, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag16 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn roundtrip_flag32( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn roundtrip_flag64( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/flegs")?; + inst.func_wrap_concurrent( + "roundtrip-flag1", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Flag1,)| + { + let host = caller; + let r = ::roundtrip_flag1(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag1,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag1,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "roundtrip-flag2", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Flag2,)| + { + let host = caller; + let r = ::roundtrip_flag2(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag2,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag2,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "roundtrip-flag4", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Flag4,)| + { + let host = caller; + let r = ::roundtrip_flag4(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag4,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag4,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "roundtrip-flag8", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Flag8,)| + { + let host = caller; + let r = ::roundtrip_flag8(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag8,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag8,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "roundtrip-flag16", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Flag16,)| + { + let host = caller; + let r = ::roundtrip_flag16(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag16,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag16,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "roundtrip-flag32", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Flag32,)| + { + let host = caller; + let r = ::roundtrip_flag32(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "roundtrip-flag64", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Flag64,)| + { + let host = caller; + let r = ::roundtrip_flag64(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag64,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Flag64,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn roundtrip_flag1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag1, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag1 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::roundtrip_flag1(store, x) + } + fn roundtrip_flag2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag2, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag2 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::roundtrip_flag2(store, x) + } + fn roundtrip_flag4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag4, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag4 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::roundtrip_flag4(store, x) + } + fn roundtrip_flag8( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag8, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag8 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::roundtrip_flag8(store, x) + } + fn roundtrip_flag16( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag16, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag16 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::roundtrip_flag16(store, x) + } + fn roundtrip_flag32( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::roundtrip_flag32(store, x) + } + fn roundtrip_flag64( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Flag64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Flag64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::roundtrip_flag64(store, x) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod flegs { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + wasmtime::component::flags!( + Flag1 { #[component(name = "b0")] const B0; } + ); + const _: () = { + assert!( + 1 == < Flag1 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < Flag1 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + wasmtime::component::flags!( + Flag2 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; } + ); + const _: () = { + assert!( + 1 == < Flag2 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < Flag2 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + wasmtime::component::flags!( + Flag4 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; #[component(name = "b2")] const B2; #[component(name = + "b3")] const B3; } + ); + const _: () = { + assert!( + 1 == < Flag4 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < Flag4 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + wasmtime::component::flags!( + Flag8 { #[component(name = "b0")] const B0; #[component(name = "b1")] + const B1; #[component(name = "b2")] const B2; #[component(name = + "b3")] const B3; #[component(name = "b4")] const B4; #[component(name + = "b5")] const B5; #[component(name = "b6")] const B6; + #[component(name = "b7")] const B7; } + ); + const _: () = { + assert!( + 1 == < Flag8 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < Flag8 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + wasmtime::component::flags!( + Flag16 { #[component(name = "b0")] const B0; #[component(name = + "b1")] const B1; #[component(name = "b2")] const B2; #[component(name + = "b3")] const B3; #[component(name = "b4")] const B4; + #[component(name = "b5")] const B5; #[component(name = "b6")] const + B6; #[component(name = "b7")] const B7; #[component(name = "b8")] + const B8; #[component(name = "b9")] const B9; #[component(name = + "b10")] const B10; #[component(name = "b11")] const B11; + #[component(name = "b12")] const B12; #[component(name = "b13")] + const B13; #[component(name = "b14")] const B14; #[component(name = + "b15")] const B15; } + ); + const _: () = { + assert!( + 2 == < Flag16 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 2 == < Flag16 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + wasmtime::component::flags!( + Flag32 { #[component(name = "b0")] const B0; #[component(name = + "b1")] const B1; #[component(name = "b2")] const B2; #[component(name + = "b3")] const B3; #[component(name = "b4")] const B4; + #[component(name = "b5")] const B5; #[component(name = "b6")] const + B6; #[component(name = "b7")] const B7; #[component(name = "b8")] + const B8; #[component(name = "b9")] const B9; #[component(name = + "b10")] const B10; #[component(name = "b11")] const B11; + #[component(name = "b12")] const B12; #[component(name = "b13")] + const B13; #[component(name = "b14")] const B14; #[component(name = + "b15")] const B15; #[component(name = "b16")] const B16; + #[component(name = "b17")] const B17; #[component(name = "b18")] + const B18; #[component(name = "b19")] const B19; #[component(name = + "b20")] const B20; #[component(name = "b21")] const B21; + #[component(name = "b22")] const B22; #[component(name = "b23")] + const B23; #[component(name = "b24")] const B24; #[component(name = + "b25")] const B25; #[component(name = "b26")] const B26; + #[component(name = "b27")] const B27; #[component(name = "b28")] + const B28; #[component(name = "b29")] const B29; #[component(name = + "b30")] const B30; #[component(name = "b31")] const B31; } + ); + const _: () = { + assert!( + 4 == < Flag32 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < Flag32 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + wasmtime::component::flags!( + Flag64 { #[component(name = "b0")] const B0; #[component(name = + "b1")] const B1; #[component(name = "b2")] const B2; #[component(name + = "b3")] const B3; #[component(name = "b4")] const B4; + #[component(name = "b5")] const B5; #[component(name = "b6")] const + B6; #[component(name = "b7")] const B7; #[component(name = "b8")] + const B8; #[component(name = "b9")] const B9; #[component(name = + "b10")] const B10; #[component(name = "b11")] const B11; + #[component(name = "b12")] const B12; #[component(name = "b13")] + const B13; #[component(name = "b14")] const B14; #[component(name = + "b15")] const B15; #[component(name = "b16")] const B16; + #[component(name = "b17")] const B17; #[component(name = "b18")] + const B18; #[component(name = "b19")] const B19; #[component(name = + "b20")] const B20; #[component(name = "b21")] const B21; + #[component(name = "b22")] const B22; #[component(name = "b23")] + const B23; #[component(name = "b24")] const B24; #[component(name = + "b25")] const B25; #[component(name = "b26")] const B26; + #[component(name = "b27")] const B27; #[component(name = "b28")] + const B28; #[component(name = "b29")] const B29; #[component(name = + "b30")] const B30; #[component(name = "b31")] const B31; + #[component(name = "b32")] const B32; #[component(name = "b33")] + const B33; #[component(name = "b34")] const B34; #[component(name = + "b35")] const B35; #[component(name = "b36")] const B36; + #[component(name = "b37")] const B37; #[component(name = "b38")] + const B38; #[component(name = "b39")] const B39; #[component(name = + "b40")] const B40; #[component(name = "b41")] const B41; + #[component(name = "b42")] const B42; #[component(name = "b43")] + const B43; #[component(name = "b44")] const B44; #[component(name = + "b45")] const B45; #[component(name = "b46")] const B46; + #[component(name = "b47")] const B47; #[component(name = "b48")] + const B48; #[component(name = "b49")] const B49; #[component(name = + "b50")] const B50; #[component(name = "b51")] const B51; + #[component(name = "b52")] const B52; #[component(name = "b53")] + const B53; #[component(name = "b54")] const B54; #[component(name = + "b55")] const B55; #[component(name = "b56")] const B56; + #[component(name = "b57")] const B57; #[component(name = "b58")] + const B58; #[component(name = "b59")] const B59; #[component(name = + "b60")] const B60; #[component(name = "b61")] const B61; + #[component(name = "b62")] const B62; #[component(name = "b63")] + const B63; } + ); + const _: () = { + assert!( + 8 == < Flag64 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < Flag64 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub struct Guest { + roundtrip_flag1: wasmtime::component::Func, + roundtrip_flag2: wasmtime::component::Func, + roundtrip_flag4: wasmtime::component::Func, + roundtrip_flag8: wasmtime::component::Func, + roundtrip_flag16: wasmtime::component::Func, + roundtrip_flag32: wasmtime::component::Func, + roundtrip_flag64: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + roundtrip_flag1: wasmtime::component::ComponentExportIndex, + roundtrip_flag2: wasmtime::component::ComponentExportIndex, + roundtrip_flag4: wasmtime::component::ComponentExportIndex, + roundtrip_flag8: wasmtime::component::ComponentExportIndex, + roundtrip_flag16: wasmtime::component::ComponentExportIndex, + roundtrip_flag32: wasmtime::component::ComponentExportIndex, + roundtrip_flag64: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/flegs") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/flegs`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/flegs") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/flegs`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/flegs` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let roundtrip_flag1 = lookup("roundtrip-flag1")?; + let roundtrip_flag2 = lookup("roundtrip-flag2")?; + let roundtrip_flag4 = lookup("roundtrip-flag4")?; + let roundtrip_flag8 = lookup("roundtrip-flag8")?; + let roundtrip_flag16 = lookup("roundtrip-flag16")?; + let roundtrip_flag32 = lookup("roundtrip-flag32")?; + let roundtrip_flag64 = lookup("roundtrip-flag64")?; + Ok(GuestIndices { + roundtrip_flag1, + roundtrip_flag2, + roundtrip_flag4, + roundtrip_flag8, + roundtrip_flag16, + roundtrip_flag32, + roundtrip_flag64, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let roundtrip_flag1 = *_instance + .get_typed_func::< + (Flag1,), + (Flag1,), + >(&mut store, &self.roundtrip_flag1)? + .func(); + let roundtrip_flag2 = *_instance + .get_typed_func::< + (Flag2,), + (Flag2,), + >(&mut store, &self.roundtrip_flag2)? + .func(); + let roundtrip_flag4 = *_instance + .get_typed_func::< + (Flag4,), + (Flag4,), + >(&mut store, &self.roundtrip_flag4)? + .func(); + let roundtrip_flag8 = *_instance + .get_typed_func::< + (Flag8,), + (Flag8,), + >(&mut store, &self.roundtrip_flag8)? + .func(); + let roundtrip_flag16 = *_instance + .get_typed_func::< + (Flag16,), + (Flag16,), + >(&mut store, &self.roundtrip_flag16)? + .func(); + let roundtrip_flag32 = *_instance + .get_typed_func::< + (Flag32,), + (Flag32,), + >(&mut store, &self.roundtrip_flag32)? + .func(); + let roundtrip_flag64 = *_instance + .get_typed_func::< + (Flag64,), + (Flag64,), + >(&mut store, &self.roundtrip_flag64)? + .func(); + Ok(Guest { + roundtrip_flag1, + roundtrip_flag2, + roundtrip_flag4, + roundtrip_flag8, + roundtrip_flag16, + roundtrip_flag32, + roundtrip_flag64, + }) + } + } + impl Guest { + pub async fn call_roundtrip_flag1( + &self, + mut store: S, + arg0: Flag1, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Flag1,), + (Flag1,), + >::new_unchecked(self.roundtrip_flag1) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_roundtrip_flag2( + &self, + mut store: S, + arg0: Flag2, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Flag2,), + (Flag2,), + >::new_unchecked(self.roundtrip_flag2) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_roundtrip_flag4( + &self, + mut store: S, + arg0: Flag4, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Flag4,), + (Flag4,), + >::new_unchecked(self.roundtrip_flag4) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_roundtrip_flag8( + &self, + mut store: S, + arg0: Flag8, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Flag8,), + (Flag8,), + >::new_unchecked(self.roundtrip_flag8) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_roundtrip_flag16( + &self, + mut store: S, + arg0: Flag16, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Flag16,), + (Flag16,), + >::new_unchecked(self.roundtrip_flag16) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_roundtrip_flag32( + &self, + mut store: S, + arg0: Flag32, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Flag32,), + (Flag32,), + >::new_unchecked(self.roundtrip_flag32) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_roundtrip_flag64( + &self, + mut store: S, + arg0: Flag64, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Flag64,), + (Flag64,), + >::new_unchecked(self.roundtrip_flag64) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/flags_tracing_async.rs b/crates/component-macro/tests/expanded/flags_tracing_async.rs index 01bfeb05ab6d..edd55612ecc6 100644 --- a/crates/component-macro/tests/expanded/flags_tracing_async.rs +++ b/crates/component-macro/tests/expanded/flags_tracing_async.rs @@ -319,19 +319,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/floats.rs b/crates/component-macro/tests/expanded/floats.rs index 89079f828361..933072287784 100644 --- a/crates/component-macro/tests/expanded/floats.rs +++ b/crates/component-macro/tests/expanded/floats.rs @@ -194,19 +194,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/floats")?; inst.func_wrap( @@ -386,7 +390,10 @@ pub mod exports { &self, mut store: S, arg0: f32, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (f32,), @@ -401,7 +408,10 @@ pub mod exports { &self, mut store: S, arg0: f64, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (f64,), @@ -415,7 +425,10 @@ pub mod exports { pub fn call_f32_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -429,7 +442,10 @@ pub mod exports { pub fn call_f64_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/floats_async.rs b/crates/component-macro/tests/expanded/floats_async.rs index 4313d8ca2b95..ef06a02aff4d 100644 --- a/crates/component-macro/tests/expanded/floats_async.rs +++ b/crates/component-macro/tests/expanded/floats_async.rs @@ -202,19 +202,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/floats_concurrent.rs b/crates/component-macro/tests/expanded/floats_concurrent.rs new file mode 100644 index 000000000000..4d7bf5d79e7c --- /dev/null +++ b/crates/component-macro/tests/expanded/floats_concurrent.rs @@ -0,0 +1,640 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::floats::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::floats::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::floats::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::floats::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::floats::Host + 'static, + U: Send + foo::foo::floats::Host, + { + foo::foo::floats::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_floats(&self) -> &exports::foo::foo::floats::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod floats { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn f32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: f32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: f64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f32_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> f32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f64_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> f64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/floats")?; + inst.func_wrap_concurrent( + "f32-param", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (f32,)| { + let host = caller; + let r = ::f32_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f64-param", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (f64,)| { + let host = caller; + let r = ::f64_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f32-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::f32_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(f32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(f32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f64-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::f64_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(f64,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(f64,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn f32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: f32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f32_param(store, x) + } + fn f64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: f64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f64_param(store, x) + } + fn f32_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> f32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f32_result(store) + } + fn f64_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> f64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f64_result(store) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod floats { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + f32_param: wasmtime::component::Func, + f64_param: wasmtime::component::Func, + f32_result: wasmtime::component::Func, + f64_result: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + f32_param: wasmtime::component::ComponentExportIndex, + f64_param: wasmtime::component::ComponentExportIndex, + f32_result: wasmtime::component::ComponentExportIndex, + f64_result: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/floats") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/floats`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/floats") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/floats`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/floats` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let f32_param = lookup("f32-param")?; + let f64_param = lookup("f64-param")?; + let f32_result = lookup("f32-result")?; + let f64_result = lookup("f64-result")?; + Ok(GuestIndices { + f32_param, + f64_param, + f32_result, + f64_result, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let f32_param = *_instance + .get_typed_func::<(f32,), ()>(&mut store, &self.f32_param)? + .func(); + let f64_param = *_instance + .get_typed_func::<(f64,), ()>(&mut store, &self.f64_param)? + .func(); + let f32_result = *_instance + .get_typed_func::<(), (f32,)>(&mut store, &self.f32_result)? + .func(); + let f64_result = *_instance + .get_typed_func::<(), (f64,)>(&mut store, &self.f64_result)? + .func(); + Ok(Guest { + f32_param, + f64_param, + f32_result, + f64_result, + }) + } + } + impl Guest { + pub async fn call_f32_param( + &self, + mut store: S, + arg0: f32, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (f32,), + (), + >::new_unchecked(self.f32_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_f64_param( + &self, + mut store: S, + arg0: f64, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (f64,), + (), + >::new_unchecked(self.f64_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_f32_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (f32,), + >::new_unchecked(self.f32_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_f64_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (f64,), + >::new_unchecked(self.f64_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/floats_tracing_async.rs b/crates/component-macro/tests/expanded/floats_tracing_async.rs index 25194e376795..e929c6f97514 100644 --- a/crates/component-macro/tests/expanded/floats_tracing_async.rs +++ b/crates/component-macro/tests/expanded/floats_tracing_async.rs @@ -202,19 +202,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/function-new.rs b/crates/component-macro/tests/expanded/function-new.rs index ca37b6668473..73cd1411780a 100644 --- a/crates/component-macro/tests/expanded/function-new.rs +++ b/crates/component-macro/tests/expanded/function-new.rs @@ -170,7 +170,10 @@ const _: () = { pub fn call_new( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::<(), ()>::new_unchecked(self.new) }; diff --git a/crates/component-macro/tests/expanded/function-new_concurrent.rs b/crates/component-macro/tests/expanded/function-new_concurrent.rs new file mode 100644 index 000000000000..4f85a363f487 --- /dev/null +++ b/crates/component-macro/tests/expanded/function-new_concurrent.rs @@ -0,0 +1,190 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `foo`. +/// +/// This structure is created through [`FooPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Foo`] as well. +pub struct FooPre { + instance_pre: wasmtime::component::InstancePre, + indices: FooIndices, +} +impl Clone for FooPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> FooPre<_T> { + /// Creates a new copy of `FooPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = FooIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Foo`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `foo`. +/// +/// This is an implementation detail of [`FooPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Foo`] as well. +#[derive(Clone)] +pub struct FooIndices { + new: wasmtime::component::ComponentExportIndex, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `foo`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Foo::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`FooPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`FooPre::instantiate_async`] to +/// create a [`Foo`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Foo::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`FooIndices::new_instance`] followed +/// by [`FooIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Foo { + new: wasmtime::component::Func, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl FooIndices { + /// Creates a new copy of `FooIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let new = _component + .export_index(None, "new") + .ok_or_else(|| anyhow::anyhow!("no function export `new` found"))? + .1; + Ok(FooIndices { new }) + } + /// Creates a new instance of [`FooIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Foo`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Foo`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let new = _instance + .get_export(&mut store, None, "new") + .ok_or_else(|| anyhow::anyhow!("no function export `new` found"))?; + Ok(FooIndices { new }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Foo`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let new = *_instance.get_typed_func::<(), ()>(&mut store, &self.new)?.func(); + Ok(Foo { new }) + } + } + impl Foo { + /// Convenience wrapper around [`FooPre::new`] and + /// [`FooPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + FooPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`FooIndices::new_instance`] and + /// [`FooIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = FooIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub async fn call_new( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::<(), ()>::new_unchecked(self.new) + }; + let promise = callee.call_concurrent(store.as_context_mut(), ()).await?; + Ok(promise) + } + } +}; diff --git a/crates/component-macro/tests/expanded/host-world.rs b/crates/component-macro/tests/expanded/host-world.rs index b5b514902114..7b976fd68428 100644 --- a/crates/component-macro/tests/expanded/host-world.rs +++ b/crates/component-macro/tests/expanded/host-world.rs @@ -97,10 +97,11 @@ pub trait Host_Imports { } pub trait Host_ImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host_Imports; } -impl Host_ImportsGetHost for F +impl Host_ImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host_Imports, @@ -175,9 +176,12 @@ const _: () = { let indices = Host_Indices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> Host_ImportsGetHost<&'a mut T, T, Host: Host_Imports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> Host_ImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut linker = linker.root(); linker diff --git a/crates/component-macro/tests/expanded/host-world_async.rs b/crates/component-macro/tests/expanded/host-world_async.rs index d6dee9406e8c..c5485f75a522 100644 --- a/crates/component-macro/tests/expanded/host-world_async.rs +++ b/crates/component-macro/tests/expanded/host-world_async.rs @@ -101,10 +101,11 @@ pub trait Host_Imports: Send { } pub trait Host_ImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host_Imports; } -impl Host_ImportsGetHost for F +impl Host_ImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host_Imports, @@ -182,9 +183,12 @@ const _: () = { let indices = Host_Indices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> Host_ImportsGetHost<&'a mut T, T, Host: Host_Imports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> Host_ImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/host-world_concurrent.rs b/crates/component-macro/tests/expanded/host-world_concurrent.rs new file mode 100644 index 000000000000..4bfb7a3e0f0e --- /dev/null +++ b/crates/component-macro/tests/expanded/host-world_concurrent.rs @@ -0,0 +1,260 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `host`. +/// +/// This structure is created through [`Host_Pre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Host_`] as well. +pub struct Host_Pre { + instance_pre: wasmtime::component::InstancePre, + indices: Host_Indices, +} +impl Clone for Host_Pre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> Host_Pre<_T> { + /// Creates a new copy of `Host_Pre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = Host_Indices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Host_`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `host`. +/// +/// This is an implementation detail of [`Host_Pre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Host_`] as well. +#[derive(Clone)] +pub struct Host_Indices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `host`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Host_::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`Host_Pre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`Host_Pre::instantiate_async`] to +/// create a [`Host_`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Host_::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`Host_Indices::new_instance`] followed +/// by [`Host_Indices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Host_ {} +pub trait Host_Imports { + type Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; +} +pub trait Host_ImportsGetHost< + T, + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host_Imports; +} +impl Host_ImportsGetHost for F +where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host_Imports, +{ + type Host = O; +} +impl<_T: Host_Imports> Host_Imports for &mut _T { + type Data = _T::Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host_Imports>::foo(store) + } +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl Host_Indices { + /// Creates a new copy of `Host_Indices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(Host_Indices {}) + } + /// Creates a new instance of [`Host_Indices`] from an + /// instantiated component. + /// + /// This method of creating a [`Host_`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Host_`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Host_Indices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Host_`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Host_ {}) + } + } + impl Host_ { + /// Convenience wrapper around [`Host_Pre::new`] and + /// [`Host_Pre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + Host_Pre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`Host_Indices::new_instance`] and + /// [`Host_Indices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = Host_Indices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> Host_ImportsGetHost<&'a mut T, T, Host: Host_Imports>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut linker = linker.root(); + linker + .func_wrap_concurrent( + "foo", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::foo(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + Host_Imports + 'static, + U: Send + Host_Imports, + { + Self::add_to_linker_imports_get_host(linker, get)?; + Ok(()) + } + } +}; diff --git a/crates/component-macro/tests/expanded/host-world_tracing_async.rs b/crates/component-macro/tests/expanded/host-world_tracing_async.rs index 8ef92dbe2326..82b0a7bbaaa4 100644 --- a/crates/component-macro/tests/expanded/host-world_tracing_async.rs +++ b/crates/component-macro/tests/expanded/host-world_tracing_async.rs @@ -101,10 +101,11 @@ pub trait Host_Imports: Send { } pub trait Host_ImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host_Imports; } -impl Host_ImportsGetHost for F +impl Host_ImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host_Imports, @@ -182,9 +183,12 @@ const _: () = { let indices = Host_Indices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> Host_ImportsGetHost<&'a mut T, T, Host: Host_Imports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> Host_ImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/integers.rs b/crates/component-macro/tests/expanded/integers.rs index fd4edcf6e1ab..d2dcc9350469 100644 --- a/crates/component-macro/tests/expanded/integers.rs +++ b/crates/component-macro/tests/expanded/integers.rs @@ -218,19 +218,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/integers")?; inst.func_wrap( @@ -714,7 +718,10 @@ pub mod exports { &self, mut store: S, arg0: u8, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u8,), @@ -729,7 +736,10 @@ pub mod exports { &self, mut store: S, arg0: i8, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (i8,), @@ -744,7 +754,10 @@ pub mod exports { &self, mut store: S, arg0: u16, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u16,), @@ -759,7 +772,10 @@ pub mod exports { &self, mut store: S, arg0: i16, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (i16,), @@ -774,7 +790,10 @@ pub mod exports { &self, mut store: S, arg0: u32, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u32,), @@ -789,7 +808,10 @@ pub mod exports { &self, mut store: S, arg0: i32, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (i32,), @@ -804,7 +826,10 @@ pub mod exports { &self, mut store: S, arg0: u64, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u64,), @@ -819,7 +844,10 @@ pub mod exports { &self, mut store: S, arg0: i64, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (i64,), @@ -841,7 +869,10 @@ pub mod exports { arg5: i32, arg6: u64, arg7: i64, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u8, i8, u16, i16, u32, i32, u64, i64), @@ -859,7 +890,10 @@ pub mod exports { pub fn call_r1( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -873,7 +907,10 @@ pub mod exports { pub fn call_r2( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -887,7 +924,10 @@ pub mod exports { pub fn call_r3( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -901,7 +941,10 @@ pub mod exports { pub fn call_r4( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -915,7 +958,10 @@ pub mod exports { pub fn call_r5( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -929,7 +975,10 @@ pub mod exports { pub fn call_r6( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -943,7 +992,10 @@ pub mod exports { pub fn call_r7( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -957,7 +1009,10 @@ pub mod exports { pub fn call_r8( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -971,7 +1026,10 @@ pub mod exports { pub fn call_pair_ret( &self, mut store: S, - ) -> wasmtime::Result<(i64, u8)> { + ) -> wasmtime::Result<(i64, u8)> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/integers_async.rs b/crates/component-macro/tests/expanded/integers_async.rs index 47045b1f6a92..f094caf1fcad 100644 --- a/crates/component-macro/tests/expanded/integers_async.rs +++ b/crates/component-macro/tests/expanded/integers_async.rs @@ -226,19 +226,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/integers_concurrent.rs b/crates/component-macro/tests/expanded/integers_concurrent.rs new file mode 100644 index 000000000000..9ee0c74534e7 --- /dev/null +++ b/crates/component-macro/tests/expanded/integers_concurrent.rs @@ -0,0 +1,1791 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::integers::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::integers::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::integers::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::integers::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::integers::Host + 'static, + U: Send + foo::foo::integers::Host, + { + foo::foo::integers::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_integers(&self) -> &exports::foo::foo::integers::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod integers { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn a1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u8, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i8, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u16, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i16, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a5( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a6( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a7( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a8( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn a9( + store: wasmtime::StoreContextMut<'_, Self::Data>, + p1: u8, + p2: i8, + p3: u16, + p4: i16, + p5: u32, + p6: i32, + p7: u64, + p8: i64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u8 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i8 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u16 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i16 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r5( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r6( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r7( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn r8( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn pair_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (i64, u8) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/integers")?; + inst.func_wrap_concurrent( + "a1", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u8,)| { + let host = caller; + let r = ::a1(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a2", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i8,)| { + let host = caller; + let r = ::a2(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a3", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u16,)| { + let host = caller; + let r = ::a3(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a4", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i16,)| { + let host = caller; + let r = ::a4(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a5", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u32,)| { + let host = caller; + let r = ::a5(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a6", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i32,)| { + let host = caller; + let r = ::a6(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a7", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u64,)| { + let host = caller; + let r = ::a7(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a8", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i64,)| { + let host = caller; + let r = ::a8(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "a9", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + ): (u8, i8, u16, i16, u32, i32, u64, i64)| + { + let host = caller; + let r = ::a9( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + ); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r1", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r1(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u8,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u8,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r2", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r2(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i8,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i8,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r3", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r3(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u16,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u16,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r4", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r4(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i16,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i16,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r5", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r5(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r6", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r6(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r7", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r7(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u64,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u64,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "r8", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::r8(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i64,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i64,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "pair-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::pair_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((i64, u8),)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((i64, u8),)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn a1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u8, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a1(store, x) + } + fn a2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i8, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a2(store, x) + } + fn a3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u16, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a3(store, x) + } + fn a4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i16, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a4(store, x) + } + fn a5( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a5(store, x) + } + fn a6( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a6(store, x) + } + fn a7( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: u64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a7(store, x) + } + fn a8( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: i64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a8(store, x) + } + fn a9( + store: wasmtime::StoreContextMut<'_, Self::Data>, + p1: u8, + p2: i8, + p3: u16, + p4: i16, + p5: u32, + p6: i32, + p7: u64, + p8: i64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a9(store, p1, p2, p3, p4, p5, p6, p7, p8) + } + fn r1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u8 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r1(store) + } + fn r2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i8 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r2(store) + } + fn r3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u16 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r3(store) + } + fn r4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i16 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r4(store) + } + fn r5( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r5(store) + } + fn r6( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r6(store) + } + fn r7( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r7(store) + } + fn r8( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i64 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::r8(store) + } + fn pair_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (i64, u8) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::pair_ret(store) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod integers { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + a1: wasmtime::component::Func, + a2: wasmtime::component::Func, + a3: wasmtime::component::Func, + a4: wasmtime::component::Func, + a5: wasmtime::component::Func, + a6: wasmtime::component::Func, + a7: wasmtime::component::Func, + a8: wasmtime::component::Func, + a9: wasmtime::component::Func, + r1: wasmtime::component::Func, + r2: wasmtime::component::Func, + r3: wasmtime::component::Func, + r4: wasmtime::component::Func, + r5: wasmtime::component::Func, + r6: wasmtime::component::Func, + r7: wasmtime::component::Func, + r8: wasmtime::component::Func, + pair_ret: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + a1: wasmtime::component::ComponentExportIndex, + a2: wasmtime::component::ComponentExportIndex, + a3: wasmtime::component::ComponentExportIndex, + a4: wasmtime::component::ComponentExportIndex, + a5: wasmtime::component::ComponentExportIndex, + a6: wasmtime::component::ComponentExportIndex, + a7: wasmtime::component::ComponentExportIndex, + a8: wasmtime::component::ComponentExportIndex, + a9: wasmtime::component::ComponentExportIndex, + r1: wasmtime::component::ComponentExportIndex, + r2: wasmtime::component::ComponentExportIndex, + r3: wasmtime::component::ComponentExportIndex, + r4: wasmtime::component::ComponentExportIndex, + r5: wasmtime::component::ComponentExportIndex, + r6: wasmtime::component::ComponentExportIndex, + r7: wasmtime::component::ComponentExportIndex, + r8: wasmtime::component::ComponentExportIndex, + pair_ret: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/integers") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/integers`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/integers") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/integers`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/integers` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let a1 = lookup("a1")?; + let a2 = lookup("a2")?; + let a3 = lookup("a3")?; + let a4 = lookup("a4")?; + let a5 = lookup("a5")?; + let a6 = lookup("a6")?; + let a7 = lookup("a7")?; + let a8 = lookup("a8")?; + let a9 = lookup("a9")?; + let r1 = lookup("r1")?; + let r2 = lookup("r2")?; + let r3 = lookup("r3")?; + let r4 = lookup("r4")?; + let r5 = lookup("r5")?; + let r6 = lookup("r6")?; + let r7 = lookup("r7")?; + let r8 = lookup("r8")?; + let pair_ret = lookup("pair-ret")?; + Ok(GuestIndices { + a1, + a2, + a3, + a4, + a5, + a6, + a7, + a8, + a9, + r1, + r2, + r3, + r4, + r5, + r6, + r7, + r8, + pair_ret, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let a1 = *_instance + .get_typed_func::<(u8,), ()>(&mut store, &self.a1)? + .func(); + let a2 = *_instance + .get_typed_func::<(i8,), ()>(&mut store, &self.a2)? + .func(); + let a3 = *_instance + .get_typed_func::<(u16,), ()>(&mut store, &self.a3)? + .func(); + let a4 = *_instance + .get_typed_func::<(i16,), ()>(&mut store, &self.a4)? + .func(); + let a5 = *_instance + .get_typed_func::<(u32,), ()>(&mut store, &self.a5)? + .func(); + let a6 = *_instance + .get_typed_func::<(i32,), ()>(&mut store, &self.a6)? + .func(); + let a7 = *_instance + .get_typed_func::<(u64,), ()>(&mut store, &self.a7)? + .func(); + let a8 = *_instance + .get_typed_func::<(i64,), ()>(&mut store, &self.a8)? + .func(); + let a9 = *_instance + .get_typed_func::< + (u8, i8, u16, i16, u32, i32, u64, i64), + (), + >(&mut store, &self.a9)? + .func(); + let r1 = *_instance + .get_typed_func::<(), (u8,)>(&mut store, &self.r1)? + .func(); + let r2 = *_instance + .get_typed_func::<(), (i8,)>(&mut store, &self.r2)? + .func(); + let r3 = *_instance + .get_typed_func::<(), (u16,)>(&mut store, &self.r3)? + .func(); + let r4 = *_instance + .get_typed_func::<(), (i16,)>(&mut store, &self.r4)? + .func(); + let r5 = *_instance + .get_typed_func::<(), (u32,)>(&mut store, &self.r5)? + .func(); + let r6 = *_instance + .get_typed_func::<(), (i32,)>(&mut store, &self.r6)? + .func(); + let r7 = *_instance + .get_typed_func::<(), (u64,)>(&mut store, &self.r7)? + .func(); + let r8 = *_instance + .get_typed_func::<(), (i64,)>(&mut store, &self.r8)? + .func(); + let pair_ret = *_instance + .get_typed_func::< + (), + ((i64, u8),), + >(&mut store, &self.pair_ret)? + .func(); + Ok(Guest { + a1, + a2, + a3, + a4, + a5, + a6, + a7, + a8, + a9, + r1, + r2, + r3, + r4, + r5, + r6, + r7, + r8, + pair_ret, + }) + } + } + impl Guest { + pub async fn call_a1( + &self, + mut store: S, + arg0: u8, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u8,), + (), + >::new_unchecked(self.a1) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a2( + &self, + mut store: S, + arg0: i8, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (i8,), + (), + >::new_unchecked(self.a2) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a3( + &self, + mut store: S, + arg0: u16, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u16,), + (), + >::new_unchecked(self.a3) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a4( + &self, + mut store: S, + arg0: i16, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (i16,), + (), + >::new_unchecked(self.a4) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a5( + &self, + mut store: S, + arg0: u32, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u32,), + (), + >::new_unchecked(self.a5) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a6( + &self, + mut store: S, + arg0: i32, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (i32,), + (), + >::new_unchecked(self.a6) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a7( + &self, + mut store: S, + arg0: u64, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u64,), + (), + >::new_unchecked(self.a7) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a8( + &self, + mut store: S, + arg0: i64, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (i64,), + (), + >::new_unchecked(self.a8) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_a9( + &self, + mut store: S, + arg0: u8, + arg1: i8, + arg2: u16, + arg3: i16, + arg4: u32, + arg5: i32, + arg6: u64, + arg7: i64, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u8, i8, u16, i16, u32, i32, u64, i64), + (), + >::new_unchecked(self.a9) + }; + let promise = callee + .call_concurrent( + store.as_context_mut(), + (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7), + ) + .await?; + Ok(promise) + } + pub async fn call_r1( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u8,), + >::new_unchecked(self.r1) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_r2( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (i8,), + >::new_unchecked(self.r2) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_r3( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u16,), + >::new_unchecked(self.r3) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_r4( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (i16,), + >::new_unchecked(self.r4) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_r5( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u32,), + >::new_unchecked(self.r5) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_r6( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (i32,), + >::new_unchecked(self.r6) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_r7( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u64,), + >::new_unchecked(self.r7) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_r8( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (i64,), + >::new_unchecked(self.r8) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_pair_ret( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + ((i64, u8),), + >::new_unchecked(self.pair_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/integers_tracing_async.rs b/crates/component-macro/tests/expanded/integers_tracing_async.rs index a8778d525cb6..6c597e0e7bb6 100644 --- a/crates/component-macro/tests/expanded/integers_tracing_async.rs +++ b/crates/component-macro/tests/expanded/integers_tracing_async.rs @@ -226,19 +226,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/lists.rs b/crates/component-macro/tests/expanded/lists.rs index bf131e0b4b01..d51b2720cd27 100644 --- a/crates/component-macro/tests/expanded/lists.rs +++ b/crates/component-macro/tests/expanded/lists.rs @@ -467,19 +467,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/lists")?; inst.func_wrap( @@ -1573,7 +1577,10 @@ pub mod exports { &self, mut store: S, arg0: &[u8], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[u8],), @@ -1588,7 +1595,10 @@ pub mod exports { &self, mut store: S, arg0: &[u16], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[u16],), @@ -1603,7 +1613,10 @@ pub mod exports { &self, mut store: S, arg0: &[u32], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[u32],), @@ -1618,7 +1631,10 @@ pub mod exports { &self, mut store: S, arg0: &[u64], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[u64],), @@ -1633,7 +1649,10 @@ pub mod exports { &self, mut store: S, arg0: &[i8], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[i8],), @@ -1648,7 +1667,10 @@ pub mod exports { &self, mut store: S, arg0: &[i16], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[i16],), @@ -1663,7 +1685,10 @@ pub mod exports { &self, mut store: S, arg0: &[i32], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[i32],), @@ -1678,7 +1703,10 @@ pub mod exports { &self, mut store: S, arg0: &[i64], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[i64],), @@ -1693,7 +1721,10 @@ pub mod exports { &self, mut store: S, arg0: &[f32], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[f32],), @@ -1708,7 +1739,10 @@ pub mod exports { &self, mut store: S, arg0: &[f64], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[f64],), @@ -1722,7 +1756,10 @@ pub mod exports { pub fn call_list_u8_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1736,7 +1773,10 @@ pub mod exports { pub fn call_list_u16_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1750,7 +1790,10 @@ pub mod exports { pub fn call_list_u32_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1764,7 +1807,10 @@ pub mod exports { pub fn call_list_u64_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1778,7 +1824,10 @@ pub mod exports { pub fn call_list_s8_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1792,7 +1841,10 @@ pub mod exports { pub fn call_list_s16_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1806,7 +1858,10 @@ pub mod exports { pub fn call_list_s32_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1820,7 +1875,10 @@ pub mod exports { pub fn call_list_s64_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1834,7 +1892,10 @@ pub mod exports { pub fn call_list_f32_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1848,7 +1909,10 @@ pub mod exports { pub fn call_list_f64_ret( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1865,7 +1929,10 @@ pub mod exports { arg0: &[(u8, i8)], ) -> wasmtime::Result< wasmtime::component::__internal::Vec<(i64, u32)>, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[(u8, i8)],), @@ -1880,7 +1947,10 @@ pub mod exports { &self, mut store: S, arg0: &[wasmtime::component::__internal::String], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[wasmtime::component::__internal::String],), @@ -1898,7 +1968,10 @@ pub mod exports { wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, >, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1921,7 +1994,10 @@ pub mod exports { wasmtime::component::__internal::Vec< (wasmtime::component::__internal::String, u8), >, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[(u8, wasmtime::component::__internal::String)],), @@ -1944,7 +2020,10 @@ pub mod exports { wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, >, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[wasmtime::component::__internal::String],), @@ -1965,7 +2044,10 @@ pub mod exports { arg0: &[SomeRecord], ) -> wasmtime::Result< wasmtime::component::__internal::Vec, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[SomeRecord],), @@ -1982,7 +2064,10 @@ pub mod exports { arg0: &[OtherRecord], ) -> wasmtime::Result< wasmtime::component::__internal::Vec, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[OtherRecord],), @@ -1999,7 +2084,10 @@ pub mod exports { arg0: &[SomeVariant], ) -> wasmtime::Result< wasmtime::component::__internal::Vec, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[SomeVariant],), @@ -2014,7 +2102,10 @@ pub mod exports { &self, mut store: S, arg0: &LoadStoreAllSizes, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&LoadStoreAllSizes,), diff --git a/crates/component-macro/tests/expanded/lists_async.rs b/crates/component-macro/tests/expanded/lists_async.rs index aa55a3f6503e..b8a48203d829 100644 --- a/crates/component-macro/tests/expanded/lists_async.rs +++ b/crates/component-macro/tests/expanded/lists_async.rs @@ -495,19 +495,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/lists_concurrent.rs b/crates/component-macro/tests/expanded/lists_concurrent.rs new file mode 100644 index 000000000000..da7af6dedcb1 --- /dev/null +++ b/crates/component-macro/tests/expanded/lists_concurrent.rs @@ -0,0 +1,3434 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-lists`. +/// +/// This structure is created through [`TheListsPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheLists`] as well. +pub struct TheListsPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheListsIndices, +} +impl Clone for TheListsPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheListsPre<_T> { + /// Creates a new copy of `TheListsPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheListsIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheLists`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-lists`. +/// +/// This is an implementation detail of [`TheListsPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheLists`] as well. +#[derive(Clone)] +pub struct TheListsIndices { + interface0: exports::foo::foo::lists::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-lists`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheLists::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheListsPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheListsPre::instantiate_async`] to +/// create a [`TheLists`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheLists::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheListsIndices::new_instance`] followed +/// by [`TheListsIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheLists { + interface0: exports::foo::foo::lists::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheListsIndices { + /// Creates a new copy of `TheListsIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::lists::GuestIndices::new(_component)?; + Ok(TheListsIndices { interface0 }) + } + /// Creates a new instance of [`TheListsIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheLists`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheLists`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::lists::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheListsIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheLists`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheLists { interface0 }) + } + } + impl TheLists { + /// Convenience wrapper around [`TheListsPre::new`] and + /// [`TheListsPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheListsPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheListsIndices::new_instance`] and + /// [`TheListsIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheListsIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::lists::Host + 'static, + U: Send + foo::foo::lists::Host, + { + foo::foo::lists::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_lists(&self) -> &exports::foo::foo::lists::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod lists { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct OtherRecord { + #[component(name = "a1")] + pub a1: u32, + #[component(name = "a2")] + pub a2: u64, + #[component(name = "a3")] + pub a3: i32, + #[component(name = "a4")] + pub a4: i64, + #[component(name = "b")] + pub b: wasmtime::component::__internal::String, + #[component(name = "c")] + pub c: wasmtime::component::__internal::Vec, + } + impl core::fmt::Debug for OtherRecord { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("OtherRecord") + .field("a1", &self.a1) + .field("a2", &self.a2) + .field("a3", &self.a3) + .field("a4", &self.a4) + .field("b", &self.b) + .field("c", &self.c) + .finish() + } + } + const _: () = { + assert!( + 48 == < OtherRecord as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 8 == < OtherRecord as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct SomeRecord { + #[component(name = "x")] + pub x: wasmtime::component::__internal::String, + #[component(name = "y")] + pub y: OtherRecord, + #[component(name = "z")] + pub z: wasmtime::component::__internal::Vec, + #[component(name = "c1")] + pub c1: u32, + #[component(name = "c2")] + pub c2: u64, + #[component(name = "c3")] + pub c3: i32, + #[component(name = "c4")] + pub c4: i64, + } + impl core::fmt::Debug for SomeRecord { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("SomeRecord") + .field("x", &self.x) + .field("y", &self.y) + .field("z", &self.z) + .field("c1", &self.c1) + .field("c2", &self.c2) + .field("c3", &self.c3) + .field("c4", &self.c4) + .finish() + } + } + const _: () = { + assert!( + 96 == < SomeRecord as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 8 == < SomeRecord as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone)] + pub enum OtherVariant { + #[component(name = "a")] + A, + #[component(name = "b")] + B(u32), + #[component(name = "c")] + C(wasmtime::component::__internal::String), + } + impl core::fmt::Debug for OtherVariant { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + OtherVariant::A => f.debug_tuple("OtherVariant::A").finish(), + OtherVariant::B(e) => { + f.debug_tuple("OtherVariant::B").field(e).finish() + } + OtherVariant::C(e) => { + f.debug_tuple("OtherVariant::C").field(e).finish() + } + } + } + } + const _: () = { + assert!( + 12 == < OtherVariant as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < OtherVariant as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone)] + pub enum SomeVariant { + #[component(name = "a")] + A(wasmtime::component::__internal::String), + #[component(name = "b")] + B, + #[component(name = "c")] + C(u32), + #[component(name = "d")] + D(wasmtime::component::__internal::Vec), + } + impl core::fmt::Debug for SomeVariant { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + SomeVariant::A(e) => { + f.debug_tuple("SomeVariant::A").field(e).finish() + } + SomeVariant::B => f.debug_tuple("SomeVariant::B").finish(), + SomeVariant::C(e) => { + f.debug_tuple("SomeVariant::C").field(e).finish() + } + SomeVariant::D(e) => { + f.debug_tuple("SomeVariant::D").field(e).finish() + } + } + } + } + const _: () = { + assert!( + 12 == < SomeVariant as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < SomeVariant as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub type LoadStoreAllSizes = wasmtime::component::__internal::Vec< + ( + wasmtime::component::__internal::String, + u8, + i8, + u16, + i16, + u32, + i32, + u64, + i64, + f32, + f64, + char, + ), + >; + const _: () = { + assert!( + 8 == < LoadStoreAllSizes as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 4 == < LoadStoreAllSizes as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub trait Host { + type Data; + fn list_u8_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_u16_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_u32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_u64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s8_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s16_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_f32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_f64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_u8_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_u16_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u16, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_u32_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_u64_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u64, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s8_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s16_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + i16, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s32_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + i32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_s64_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + i64, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_f32_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + f32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_f64_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + f64, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn tuple_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec<(u8, i8)>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + (i64, u32), + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn string_list_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn string_list_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn tuple_string_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + (u8, wasmtime::component::__internal::String), + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + (wasmtime::component::__internal::String, u8), + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn string_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn record_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + OtherRecord, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn record_list_reverse( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + SomeRecord, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn variant_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + OtherVariant, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn load_store_everything( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: LoadStoreAllSizes, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> LoadStoreAllSizes + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/lists")?; + inst.func_wrap_concurrent( + "list-u8-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_u8_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-u16-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_u16_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-u32-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_u32_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-u64-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_u64_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s8-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_s8_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s16-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_s16_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s32-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_s32_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s64-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_s64_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-f32-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_f32_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-f64-param", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::list_f64_param(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-u8-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_u8_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-u16-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_u16_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-u32-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_u32_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-u64-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_u64_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s8-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_s8_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s16-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_s16_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s32-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_s32_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-s64-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_s64_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-f32-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_f32_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-f64-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_f64_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "tuple-list", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec<(u8, i8)>,)| + { + let host = caller; + let r = ::tuple_list(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec<(i64, u32)>,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec<(i64, u32)>,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "string-list-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + ): ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + )| + { + let host = caller; + let r = ::string_list_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "string-list-ret", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::string_list_ret(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "tuple-string-list", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + ): ( + wasmtime::component::__internal::Vec< + (u8, wasmtime::component::__internal::String), + >, + )| + { + let host = caller; + let r = ::tuple_string_list(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + (wasmtime::component::__internal::String, u8), + >, + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + (wasmtime::component::__internal::String, u8), + >, + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "string-list", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + ): ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + )| + { + let host = caller; + let r = ::string_list(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "record-list", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::record_list(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "record-list-reverse", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::record_list_reverse(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "variant-list", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::variant_list(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "load-store-everything", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (LoadStoreAllSizes,)| + { + let host = caller; + let r = ::load_store_everything(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(LoadStoreAllSizes,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(LoadStoreAllSizes,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn list_u8_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u8_param(store, x) + } + fn list_u16_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u16_param(store, x) + } + fn list_u32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u32_param(store, x) + } + fn list_u64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u64_param(store, x) + } + fn list_s8_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s8_param(store, x) + } + fn list_s16_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s16_param(store, x) + } + fn list_s32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s32_param(store, x) + } + fn list_s64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s64_param(store, x) + } + fn list_f32_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_f32_param(store, x) + } + fn list_f64_param( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_f64_param(store, x) + } + fn list_u8_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u8_ret(store) + } + fn list_u16_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u16, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u16_ret(store) + } + fn list_u32_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u32_ret(store) + } + fn list_u64_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u64, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_u64_ret(store) + } + fn list_s8_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s8_ret(store) + } + fn list_s16_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + i16, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s16_ret(store) + } + fn list_s32_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + i32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s32_ret(store) + } + fn list_s64_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + i64, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_s64_ret(store) + } + fn list_f32_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + f32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_f32_ret(store) + } + fn list_f64_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + f64, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_f64_ret(store) + } + fn tuple_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec<(u8, i8)>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + (i64, u32), + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::tuple_list(store, x) + } + fn string_list_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::string_list_arg(store, a) + } + fn string_list_ret( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::string_list_ret(store) + } + fn tuple_string_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + (u8, wasmtime::component::__internal::String), + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + (wasmtime::component::__internal::String, u8), + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::tuple_string_list(store, x) + } + fn string_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::string_list(store, x) + } + fn record_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + OtherRecord, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::record_list(store, x) + } + fn record_list_reverse( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + SomeRecord, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::record_list_reverse(store, x) + } + fn variant_list( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + OtherVariant, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::variant_list(store, x) + } + fn load_store_everything( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: LoadStoreAllSizes, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> LoadStoreAllSizes + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::load_store_everything(store, a) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod lists { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct OtherRecord { + #[component(name = "a1")] + pub a1: u32, + #[component(name = "a2")] + pub a2: u64, + #[component(name = "a3")] + pub a3: i32, + #[component(name = "a4")] + pub a4: i64, + #[component(name = "b")] + pub b: wasmtime::component::__internal::String, + #[component(name = "c")] + pub c: wasmtime::component::__internal::Vec, + } + impl core::fmt::Debug for OtherRecord { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("OtherRecord") + .field("a1", &self.a1) + .field("a2", &self.a2) + .field("a3", &self.a3) + .field("a4", &self.a4) + .field("b", &self.b) + .field("c", &self.c) + .finish() + } + } + const _: () = { + assert!( + 48 == < OtherRecord as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 8 == < OtherRecord as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct SomeRecord { + #[component(name = "x")] + pub x: wasmtime::component::__internal::String, + #[component(name = "y")] + pub y: OtherRecord, + #[component(name = "z")] + pub z: wasmtime::component::__internal::Vec, + #[component(name = "c1")] + pub c1: u32, + #[component(name = "c2")] + pub c2: u64, + #[component(name = "c3")] + pub c3: i32, + #[component(name = "c4")] + pub c4: i64, + } + impl core::fmt::Debug for SomeRecord { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("SomeRecord") + .field("x", &self.x) + .field("y", &self.y) + .field("z", &self.z) + .field("c1", &self.c1) + .field("c2", &self.c2) + .field("c3", &self.c3) + .field("c4", &self.c4) + .finish() + } + } + const _: () = { + assert!( + 96 == < SomeRecord as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 8 == < SomeRecord as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone)] + pub enum OtherVariant { + #[component(name = "a")] + A, + #[component(name = "b")] + B(u32), + #[component(name = "c")] + C(wasmtime::component::__internal::String), + } + impl core::fmt::Debug for OtherVariant { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + OtherVariant::A => f.debug_tuple("OtherVariant::A").finish(), + OtherVariant::B(e) => { + f.debug_tuple("OtherVariant::B").field(e).finish() + } + OtherVariant::C(e) => { + f.debug_tuple("OtherVariant::C").field(e).finish() + } + } + } + } + const _: () = { + assert!( + 12 == < OtherVariant as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 4 == < OtherVariant as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone)] + pub enum SomeVariant { + #[component(name = "a")] + A(wasmtime::component::__internal::String), + #[component(name = "b")] + B, + #[component(name = "c")] + C(u32), + #[component(name = "d")] + D(wasmtime::component::__internal::Vec), + } + impl core::fmt::Debug for SomeVariant { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + SomeVariant::A(e) => { + f.debug_tuple("SomeVariant::A").field(e).finish() + } + SomeVariant::B => f.debug_tuple("SomeVariant::B").finish(), + SomeVariant::C(e) => { + f.debug_tuple("SomeVariant::C").field(e).finish() + } + SomeVariant::D(e) => { + f.debug_tuple("SomeVariant::D").field(e).finish() + } + } + } + } + const _: () = { + assert!( + 12 == < SomeVariant as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 4 == < SomeVariant as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub type LoadStoreAllSizes = wasmtime::component::__internal::Vec< + ( + wasmtime::component::__internal::String, + u8, + i8, + u16, + i16, + u32, + i32, + u64, + i64, + f32, + f64, + char, + ), + >; + const _: () = { + assert!( + 8 == < LoadStoreAllSizes as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 4 == < LoadStoreAllSizes as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub struct Guest { + list_u8_param: wasmtime::component::Func, + list_u16_param: wasmtime::component::Func, + list_u32_param: wasmtime::component::Func, + list_u64_param: wasmtime::component::Func, + list_s8_param: wasmtime::component::Func, + list_s16_param: wasmtime::component::Func, + list_s32_param: wasmtime::component::Func, + list_s64_param: wasmtime::component::Func, + list_f32_param: wasmtime::component::Func, + list_f64_param: wasmtime::component::Func, + list_u8_ret: wasmtime::component::Func, + list_u16_ret: wasmtime::component::Func, + list_u32_ret: wasmtime::component::Func, + list_u64_ret: wasmtime::component::Func, + list_s8_ret: wasmtime::component::Func, + list_s16_ret: wasmtime::component::Func, + list_s32_ret: wasmtime::component::Func, + list_s64_ret: wasmtime::component::Func, + list_f32_ret: wasmtime::component::Func, + list_f64_ret: wasmtime::component::Func, + tuple_list: wasmtime::component::Func, + string_list_arg: wasmtime::component::Func, + string_list_ret: wasmtime::component::Func, + tuple_string_list: wasmtime::component::Func, + string_list: wasmtime::component::Func, + record_list: wasmtime::component::Func, + record_list_reverse: wasmtime::component::Func, + variant_list: wasmtime::component::Func, + load_store_everything: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + list_u8_param: wasmtime::component::ComponentExportIndex, + list_u16_param: wasmtime::component::ComponentExportIndex, + list_u32_param: wasmtime::component::ComponentExportIndex, + list_u64_param: wasmtime::component::ComponentExportIndex, + list_s8_param: wasmtime::component::ComponentExportIndex, + list_s16_param: wasmtime::component::ComponentExportIndex, + list_s32_param: wasmtime::component::ComponentExportIndex, + list_s64_param: wasmtime::component::ComponentExportIndex, + list_f32_param: wasmtime::component::ComponentExportIndex, + list_f64_param: wasmtime::component::ComponentExportIndex, + list_u8_ret: wasmtime::component::ComponentExportIndex, + list_u16_ret: wasmtime::component::ComponentExportIndex, + list_u32_ret: wasmtime::component::ComponentExportIndex, + list_u64_ret: wasmtime::component::ComponentExportIndex, + list_s8_ret: wasmtime::component::ComponentExportIndex, + list_s16_ret: wasmtime::component::ComponentExportIndex, + list_s32_ret: wasmtime::component::ComponentExportIndex, + list_s64_ret: wasmtime::component::ComponentExportIndex, + list_f32_ret: wasmtime::component::ComponentExportIndex, + list_f64_ret: wasmtime::component::ComponentExportIndex, + tuple_list: wasmtime::component::ComponentExportIndex, + string_list_arg: wasmtime::component::ComponentExportIndex, + string_list_ret: wasmtime::component::ComponentExportIndex, + tuple_string_list: wasmtime::component::ComponentExportIndex, + string_list: wasmtime::component::ComponentExportIndex, + record_list: wasmtime::component::ComponentExportIndex, + record_list_reverse: wasmtime::component::ComponentExportIndex, + variant_list: wasmtime::component::ComponentExportIndex, + load_store_everything: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/lists") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/lists`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/lists") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/lists`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/lists` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let list_u8_param = lookup("list-u8-param")?; + let list_u16_param = lookup("list-u16-param")?; + let list_u32_param = lookup("list-u32-param")?; + let list_u64_param = lookup("list-u64-param")?; + let list_s8_param = lookup("list-s8-param")?; + let list_s16_param = lookup("list-s16-param")?; + let list_s32_param = lookup("list-s32-param")?; + let list_s64_param = lookup("list-s64-param")?; + let list_f32_param = lookup("list-f32-param")?; + let list_f64_param = lookup("list-f64-param")?; + let list_u8_ret = lookup("list-u8-ret")?; + let list_u16_ret = lookup("list-u16-ret")?; + let list_u32_ret = lookup("list-u32-ret")?; + let list_u64_ret = lookup("list-u64-ret")?; + let list_s8_ret = lookup("list-s8-ret")?; + let list_s16_ret = lookup("list-s16-ret")?; + let list_s32_ret = lookup("list-s32-ret")?; + let list_s64_ret = lookup("list-s64-ret")?; + let list_f32_ret = lookup("list-f32-ret")?; + let list_f64_ret = lookup("list-f64-ret")?; + let tuple_list = lookup("tuple-list")?; + let string_list_arg = lookup("string-list-arg")?; + let string_list_ret = lookup("string-list-ret")?; + let tuple_string_list = lookup("tuple-string-list")?; + let string_list = lookup("string-list")?; + let record_list = lookup("record-list")?; + let record_list_reverse = lookup("record-list-reverse")?; + let variant_list = lookup("variant-list")?; + let load_store_everything = lookup("load-store-everything")?; + Ok(GuestIndices { + list_u8_param, + list_u16_param, + list_u32_param, + list_u64_param, + list_s8_param, + list_s16_param, + list_s32_param, + list_s64_param, + list_f32_param, + list_f64_param, + list_u8_ret, + list_u16_ret, + list_u32_ret, + list_u64_ret, + list_s8_ret, + list_s16_ret, + list_s32_ret, + list_s64_ret, + list_f32_ret, + list_f64_ret, + tuple_list, + string_list_arg, + string_list_ret, + tuple_string_list, + string_list, + record_list, + record_list_reverse, + variant_list, + load_store_everything, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let list_u8_param = *_instance + .get_typed_func::< + (&[u8],), + (), + >(&mut store, &self.list_u8_param)? + .func(); + let list_u16_param = *_instance + .get_typed_func::< + (&[u16],), + (), + >(&mut store, &self.list_u16_param)? + .func(); + let list_u32_param = *_instance + .get_typed_func::< + (&[u32],), + (), + >(&mut store, &self.list_u32_param)? + .func(); + let list_u64_param = *_instance + .get_typed_func::< + (&[u64],), + (), + >(&mut store, &self.list_u64_param)? + .func(); + let list_s8_param = *_instance + .get_typed_func::< + (&[i8],), + (), + >(&mut store, &self.list_s8_param)? + .func(); + let list_s16_param = *_instance + .get_typed_func::< + (&[i16],), + (), + >(&mut store, &self.list_s16_param)? + .func(); + let list_s32_param = *_instance + .get_typed_func::< + (&[i32],), + (), + >(&mut store, &self.list_s32_param)? + .func(); + let list_s64_param = *_instance + .get_typed_func::< + (&[i64],), + (), + >(&mut store, &self.list_s64_param)? + .func(); + let list_f32_param = *_instance + .get_typed_func::< + (&[f32],), + (), + >(&mut store, &self.list_f32_param)? + .func(); + let list_f64_param = *_instance + .get_typed_func::< + (&[f64],), + (), + >(&mut store, &self.list_f64_param)? + .func(); + let list_u8_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_u8_ret)? + .func(); + let list_u16_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_u16_ret)? + .func(); + let list_u32_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_u32_ret)? + .func(); + let list_u64_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_u64_ret)? + .func(); + let list_s8_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_s8_ret)? + .func(); + let list_s16_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_s16_ret)? + .func(); + let list_s32_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_s32_ret)? + .func(); + let list_s64_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_s64_ret)? + .func(); + let list_f32_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_f32_ret)? + .func(); + let list_f64_ret = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.list_f64_ret)? + .func(); + let tuple_list = *_instance + .get_typed_func::< + (&[(u8, i8)],), + (wasmtime::component::__internal::Vec<(i64, u32)>,), + >(&mut store, &self.tuple_list)? + .func(); + let string_list_arg = *_instance + .get_typed_func::< + (&[wasmtime::component::__internal::String],), + (), + >(&mut store, &self.string_list_arg)? + .func(); + let string_list_ret = *_instance + .get_typed_func::< + (), + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + >(&mut store, &self.string_list_ret)? + .func(); + let tuple_string_list = *_instance + .get_typed_func::< + (&[(u8, wasmtime::component::__internal::String)],), + ( + wasmtime::component::__internal::Vec< + (wasmtime::component::__internal::String, u8), + >, + ), + >(&mut store, &self.tuple_string_list)? + .func(); + let string_list = *_instance + .get_typed_func::< + (&[wasmtime::component::__internal::String],), + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + >(&mut store, &self.string_list)? + .func(); + let record_list = *_instance + .get_typed_func::< + (&[SomeRecord],), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.record_list)? + .func(); + let record_list_reverse = *_instance + .get_typed_func::< + (&[OtherRecord],), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.record_list_reverse)? + .func(); + let variant_list = *_instance + .get_typed_func::< + (&[SomeVariant],), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.variant_list)? + .func(); + let load_store_everything = *_instance + .get_typed_func::< + (&LoadStoreAllSizes,), + (LoadStoreAllSizes,), + >(&mut store, &self.load_store_everything)? + .func(); + Ok(Guest { + list_u8_param, + list_u16_param, + list_u32_param, + list_u64_param, + list_s8_param, + list_s16_param, + list_s32_param, + list_s64_param, + list_f32_param, + list_f64_param, + list_u8_ret, + list_u16_ret, + list_u32_ret, + list_u64_ret, + list_s8_ret, + list_s16_ret, + list_s32_ret, + list_s64_ret, + list_f32_ret, + list_f64_ret, + tuple_list, + string_list_arg, + string_list_ret, + tuple_string_list, + string_list, + record_list, + record_list_reverse, + variant_list, + load_store_everything, + }) + } + } + impl Guest { + pub async fn call_list_u8_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_u8_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_u16_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_u16_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_u32_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_u32_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_u64_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_u64_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_s8_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_s8_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_s16_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_s16_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_s32_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_s32_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_s64_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_s64_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_f32_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_f32_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_f64_param( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.list_f64_param) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_list_u8_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_u8_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_u16_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_u16_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_u32_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_u32_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_u64_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_u64_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_s8_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_s8_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_s16_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_s16_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_s32_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_s32_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_s64_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_s64_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_f32_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_f32_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_list_f64_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.list_f64_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_tuple_list( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec<(u8, i8)>, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec<(i64, u32)>, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec<(u8, i8)>,), + (wasmtime::component::__internal::Vec<(i64, u32)>,), + >::new_unchecked(self.tuple_list) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_string_list_arg( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + (), + >::new_unchecked(self.string_list_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_string_list_ret( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + >::new_unchecked(self.string_list_ret) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_tuple_string_list( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec< + (u8, wasmtime::component::__internal::String), + >, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec< + (wasmtime::component::__internal::String, u8), + >, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + wasmtime::component::__internal::Vec< + (u8, wasmtime::component::__internal::String), + >, + ), + ( + wasmtime::component::__internal::Vec< + (wasmtime::component::__internal::String, u8), + >, + ), + >::new_unchecked(self.tuple_string_list) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_string_list( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::String, + >, + ), + >::new_unchecked(self.string_list) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_record_list( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.record_list) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_record_list_reverse( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.record_list_reverse) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_variant_list( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.variant_list) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_load_store_everything( + &self, + mut store: S, + arg0: LoadStoreAllSizes, + ) -> wasmtime::Result< + wasmtime::component::Promise, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (LoadStoreAllSizes,), + (LoadStoreAllSizes,), + >::new_unchecked(self.load_store_everything) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/lists_tracing_async.rs b/crates/component-macro/tests/expanded/lists_tracing_async.rs index a1e470bea83f..c0d9416191d8 100644 --- a/crates/component-macro/tests/expanded/lists_tracing_async.rs +++ b/crates/component-macro/tests/expanded/lists_tracing_async.rs @@ -495,19 +495,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/many-arguments.rs b/crates/component-macro/tests/expanded/many-arguments.rs index 615876268b88..075f232aaaa8 100644 --- a/crates/component-macro/tests/expanded/many-arguments.rs +++ b/crates/component-macro/tests/expanded/many-arguments.rs @@ -291,19 +291,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/manyarg")?; inst.func_wrap( @@ -659,7 +663,10 @@ pub mod exports { arg13: u64, arg14: u64, arg15: u64, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< ( @@ -712,7 +719,10 @@ pub mod exports { &self, mut store: S, arg0: &BigStruct, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&BigStruct,), diff --git a/crates/component-macro/tests/expanded/many-arguments_async.rs b/crates/component-macro/tests/expanded/many-arguments_async.rs index 1f454d623998..661d620abcdb 100644 --- a/crates/component-macro/tests/expanded/many-arguments_async.rs +++ b/crates/component-macro/tests/expanded/many-arguments_async.rs @@ -299,19 +299,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/many-arguments_concurrent.rs b/crates/component-macro/tests/expanded/many-arguments_concurrent.rs new file mode 100644 index 000000000000..e69d90662a6e --- /dev/null +++ b/crates/component-macro/tests/expanded/many-arguments_concurrent.rs @@ -0,0 +1,830 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::manyarg::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::manyarg::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::manyarg::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::manyarg::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::manyarg::Host + 'static, + U: Send + foo::foo::manyarg::Host, + { + foo::foo::manyarg::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_manyarg(&self) -> &exports::foo::foo::manyarg::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod manyarg { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct BigStruct { + #[component(name = "a1")] + pub a1: wasmtime::component::__internal::String, + #[component(name = "a2")] + pub a2: wasmtime::component::__internal::String, + #[component(name = "a3")] + pub a3: wasmtime::component::__internal::String, + #[component(name = "a4")] + pub a4: wasmtime::component::__internal::String, + #[component(name = "a5")] + pub a5: wasmtime::component::__internal::String, + #[component(name = "a6")] + pub a6: wasmtime::component::__internal::String, + #[component(name = "a7")] + pub a7: wasmtime::component::__internal::String, + #[component(name = "a8")] + pub a8: wasmtime::component::__internal::String, + #[component(name = "a9")] + pub a9: wasmtime::component::__internal::String, + #[component(name = "a10")] + pub a10: wasmtime::component::__internal::String, + #[component(name = "a11")] + pub a11: wasmtime::component::__internal::String, + #[component(name = "a12")] + pub a12: wasmtime::component::__internal::String, + #[component(name = "a13")] + pub a13: wasmtime::component::__internal::String, + #[component(name = "a14")] + pub a14: wasmtime::component::__internal::String, + #[component(name = "a15")] + pub a15: wasmtime::component::__internal::String, + #[component(name = "a16")] + pub a16: wasmtime::component::__internal::String, + #[component(name = "a17")] + pub a17: wasmtime::component::__internal::String, + #[component(name = "a18")] + pub a18: wasmtime::component::__internal::String, + #[component(name = "a19")] + pub a19: wasmtime::component::__internal::String, + #[component(name = "a20")] + pub a20: wasmtime::component::__internal::String, + } + impl core::fmt::Debug for BigStruct { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("BigStruct") + .field("a1", &self.a1) + .field("a2", &self.a2) + .field("a3", &self.a3) + .field("a4", &self.a4) + .field("a5", &self.a5) + .field("a6", &self.a6) + .field("a7", &self.a7) + .field("a8", &self.a8) + .field("a9", &self.a9) + .field("a10", &self.a10) + .field("a11", &self.a11) + .field("a12", &self.a12) + .field("a13", &self.a13) + .field("a14", &self.a14) + .field("a15", &self.a15) + .field("a16", &self.a16) + .field("a17", &self.a17) + .field("a18", &self.a18) + .field("a19", &self.a19) + .field("a20", &self.a20) + .finish() + } + } + const _: () = { + assert!( + 160 == < BigStruct as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < BigStruct as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub trait Host { + type Data; + fn many_args( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a1: u64, + a2: u64, + a3: u64, + a4: u64, + a5: u64, + a6: u64, + a7: u64, + a8: u64, + a9: u64, + a10: u64, + a11: u64, + a12: u64, + a13: u64, + a14: u64, + a15: u64, + a16: u64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn big_argument( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: BigStruct, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/manyarg")?; + inst.func_wrap_concurrent( + "many-args", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + ): ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + )| + { + let host = caller; + let r = ::many_args( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + ); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "big-argument", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (BigStruct,)| + { + let host = caller; + let r = ::big_argument(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn many_args( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a1: u64, + a2: u64, + a3: u64, + a4: u64, + a5: u64, + a6: u64, + a7: u64, + a8: u64, + a9: u64, + a10: u64, + a11: u64, + a12: u64, + a13: u64, + a14: u64, + a15: u64, + a16: u64, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::many_args( + store, + a1, + a2, + a3, + a4, + a5, + a6, + a7, + a8, + a9, + a10, + a11, + a12, + a13, + a14, + a15, + a16, + ) + } + fn big_argument( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: BigStruct, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::big_argument(store, x) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod manyarg { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct BigStruct { + #[component(name = "a1")] + pub a1: wasmtime::component::__internal::String, + #[component(name = "a2")] + pub a2: wasmtime::component::__internal::String, + #[component(name = "a3")] + pub a3: wasmtime::component::__internal::String, + #[component(name = "a4")] + pub a4: wasmtime::component::__internal::String, + #[component(name = "a5")] + pub a5: wasmtime::component::__internal::String, + #[component(name = "a6")] + pub a6: wasmtime::component::__internal::String, + #[component(name = "a7")] + pub a7: wasmtime::component::__internal::String, + #[component(name = "a8")] + pub a8: wasmtime::component::__internal::String, + #[component(name = "a9")] + pub a9: wasmtime::component::__internal::String, + #[component(name = "a10")] + pub a10: wasmtime::component::__internal::String, + #[component(name = "a11")] + pub a11: wasmtime::component::__internal::String, + #[component(name = "a12")] + pub a12: wasmtime::component::__internal::String, + #[component(name = "a13")] + pub a13: wasmtime::component::__internal::String, + #[component(name = "a14")] + pub a14: wasmtime::component::__internal::String, + #[component(name = "a15")] + pub a15: wasmtime::component::__internal::String, + #[component(name = "a16")] + pub a16: wasmtime::component::__internal::String, + #[component(name = "a17")] + pub a17: wasmtime::component::__internal::String, + #[component(name = "a18")] + pub a18: wasmtime::component::__internal::String, + #[component(name = "a19")] + pub a19: wasmtime::component::__internal::String, + #[component(name = "a20")] + pub a20: wasmtime::component::__internal::String, + } + impl core::fmt::Debug for BigStruct { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("BigStruct") + .field("a1", &self.a1) + .field("a2", &self.a2) + .field("a3", &self.a3) + .field("a4", &self.a4) + .field("a5", &self.a5) + .field("a6", &self.a6) + .field("a7", &self.a7) + .field("a8", &self.a8) + .field("a9", &self.a9) + .field("a10", &self.a10) + .field("a11", &self.a11) + .field("a12", &self.a12) + .field("a13", &self.a13) + .field("a14", &self.a14) + .field("a15", &self.a15) + .field("a16", &self.a16) + .field("a17", &self.a17) + .field("a18", &self.a18) + .field("a19", &self.a19) + .field("a20", &self.a20) + .finish() + } + } + const _: () = { + assert!( + 160 == < BigStruct as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 4 == < BigStruct as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub struct Guest { + many_args: wasmtime::component::Func, + big_argument: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + many_args: wasmtime::component::ComponentExportIndex, + big_argument: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/manyarg") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/manyarg`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/manyarg") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/manyarg`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/manyarg` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let many_args = lookup("many-args")?; + let big_argument = lookup("big-argument")?; + Ok(GuestIndices { + many_args, + big_argument, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let many_args = *_instance + .get_typed_func::< + ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ), + (), + >(&mut store, &self.many_args)? + .func(); + let big_argument = *_instance + .get_typed_func::< + (&BigStruct,), + (), + >(&mut store, &self.big_argument)? + .func(); + Ok(Guest { many_args, big_argument }) + } + } + impl Guest { + pub async fn call_many_args( + &self, + mut store: S, + arg0: u64, + arg1: u64, + arg2: u64, + arg3: u64, + arg4: u64, + arg5: u64, + arg6: u64, + arg7: u64, + arg8: u64, + arg9: u64, + arg10: u64, + arg11: u64, + arg12: u64, + arg13: u64, + arg14: u64, + arg15: u64, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ), + (), + >::new_unchecked(self.many_args) + }; + let promise = callee + .call_concurrent( + store.as_context_mut(), + ( + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + ), + ) + .await?; + Ok(promise) + } + pub async fn call_big_argument( + &self, + mut store: S, + arg0: BigStruct, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (BigStruct,), + (), + >::new_unchecked(self.big_argument) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/many-arguments_tracing_async.rs b/crates/component-macro/tests/expanded/many-arguments_tracing_async.rs index 334616870f8a..3865f80c8afd 100644 --- a/crates/component-macro/tests/expanded/many-arguments_tracing_async.rs +++ b/crates/component-macro/tests/expanded/many-arguments_tracing_async.rs @@ -299,19 +299,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/multi-return.rs b/crates/component-macro/tests/expanded/multi-return.rs index dd0637fbeb4b..3ef8c1341061 100644 --- a/crates/component-macro/tests/expanded/multi-return.rs +++ b/crates/component-macro/tests/expanded/multi-return.rs @@ -197,19 +197,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/multi-return")?; inst.func_wrap( @@ -401,7 +405,10 @@ pub mod exports { pub fn call_mra( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -415,7 +422,10 @@ pub mod exports { pub fn call_mrb( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -429,7 +439,10 @@ pub mod exports { pub fn call_mrc( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -443,7 +456,10 @@ pub mod exports { pub fn call_mrd( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -457,7 +473,10 @@ pub mod exports { pub fn call_mre( &self, mut store: S, - ) -> wasmtime::Result<(u32, f32)> { + ) -> wasmtime::Result<(u32, f32)> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/multi-return_async.rs b/crates/component-macro/tests/expanded/multi-return_async.rs index 2b434520c89c..048b5dd2a72d 100644 --- a/crates/component-macro/tests/expanded/multi-return_async.rs +++ b/crates/component-macro/tests/expanded/multi-return_async.rs @@ -205,19 +205,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/multi-return_concurrent.rs b/crates/component-macro/tests/expanded/multi-return_concurrent.rs new file mode 100644 index 000000000000..a3fe32a8440d --- /dev/null +++ b/crates/component-macro/tests/expanded/multi-return_concurrent.rs @@ -0,0 +1,707 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::multi_return::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::multi_return::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::multi_return::GuestIndices::new( + _component, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::multi_return::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::multi_return::Host + 'static, + U: Send + foo::foo::multi_return::Host, + { + foo::foo::multi_return::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_multi_return(&self) -> &exports::foo::foo::multi_return::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod multi_return { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn mra( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn mrb( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn mrc( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn mrd( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn mre( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (u32, f32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/multi-return")?; + inst.func_wrap_concurrent( + "mra", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::mra(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "mrb", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::mrb(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "mrc", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::mrc(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "mrd", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::mrd(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "mre", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::mre(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32, f32)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32, f32)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn mra( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::mra(store) + } + fn mrb( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::mrb(store) + } + fn mrc( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::mrc(store) + } + fn mrd( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::mrd(store) + } + fn mre( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (u32, f32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::mre(store) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod multi_return { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + mra: wasmtime::component::Func, + mrb: wasmtime::component::Func, + mrc: wasmtime::component::Func, + mrd: wasmtime::component::Func, + mre: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + mra: wasmtime::component::ComponentExportIndex, + mrb: wasmtime::component::ComponentExportIndex, + mrc: wasmtime::component::ComponentExportIndex, + mrd: wasmtime::component::ComponentExportIndex, + mre: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/multi-return") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/multi-return`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/multi-return") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/multi-return`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/multi-return` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let mra = lookup("mra")?; + let mrb = lookup("mrb")?; + let mrc = lookup("mrc")?; + let mrd = lookup("mrd")?; + let mre = lookup("mre")?; + Ok(GuestIndices { + mra, + mrb, + mrc, + mrd, + mre, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let mra = *_instance + .get_typed_func::<(), ()>(&mut store, &self.mra)? + .func(); + let mrb = *_instance + .get_typed_func::<(), ()>(&mut store, &self.mrb)? + .func(); + let mrc = *_instance + .get_typed_func::<(), (u32,)>(&mut store, &self.mrc)? + .func(); + let mrd = *_instance + .get_typed_func::<(), (u32,)>(&mut store, &self.mrd)? + .func(); + let mre = *_instance + .get_typed_func::<(), (u32, f32)>(&mut store, &self.mre)? + .func(); + Ok(Guest { mra, mrb, mrc, mrd, mre }) + } + } + impl Guest { + pub async fn call_mra( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.mra) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_mrb( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.mrb) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_mrc( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u32,), + >::new_unchecked(self.mrc) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_mrd( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u32,), + >::new_unchecked(self.mrd) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_mre( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u32, f32), + >::new_unchecked(self.mre) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/multi-return_tracing_async.rs b/crates/component-macro/tests/expanded/multi-return_tracing_async.rs index ca9c503e58b7..aa0f428f6ea9 100644 --- a/crates/component-macro/tests/expanded/multi-return_tracing_async.rs +++ b/crates/component-macro/tests/expanded/multi-return_tracing_async.rs @@ -205,19 +205,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/multiversion.rs b/crates/component-macro/tests/expanded/multiversion.rs index da50b12799ea..f7ee57f69785 100644 --- a/crates/component-macro/tests/expanded/multiversion.rs +++ b/crates/component-macro/tests/expanded/multiversion.rs @@ -209,19 +209,23 @@ pub mod my { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("my:dep/a@0.1.0")?; inst.func_wrap( @@ -260,19 +264,23 @@ pub mod my { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("my:dep/a@0.2.0")?; inst.func_wrap( @@ -390,7 +398,10 @@ pub mod exports { pub fn call_x( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -490,7 +501,10 @@ pub mod exports { pub fn call_x( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/multiversion_async.rs b/crates/component-macro/tests/expanded/multiversion_async.rs index 885c0ce1b69b..d490e92a65a1 100644 --- a/crates/component-macro/tests/expanded/multiversion_async.rs +++ b/crates/component-macro/tests/expanded/multiversion_async.rs @@ -217,19 +217,23 @@ pub mod my { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -275,19 +279,23 @@ pub mod my { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/multiversion_concurrent.rs b/crates/component-macro/tests/expanded/multiversion_concurrent.rs new file mode 100644 index 000000000000..5613af6479a5 --- /dev/null +++ b/crates/component-macro/tests/expanded/multiversion_concurrent.rs @@ -0,0 +1,622 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `foo`. +/// +/// This structure is created through [`FooPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Foo`] as well. +pub struct FooPre { + instance_pre: wasmtime::component::InstancePre, + indices: FooIndices, +} +impl Clone for FooPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> FooPre<_T> { + /// Creates a new copy of `FooPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = FooIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Foo`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `foo`. +/// +/// This is an implementation detail of [`FooPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Foo`] as well. +#[derive(Clone)] +pub struct FooIndices { + interface0: exports::my::dep0_1_0::a::GuestIndices, + interface1: exports::my::dep0_2_0::a::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `foo`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Foo::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`FooPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`FooPre::instantiate_async`] to +/// create a [`Foo`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Foo::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`FooIndices::new_instance`] followed +/// by [`FooIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Foo { + interface0: exports::my::dep0_1_0::a::Guest, + interface1: exports::my::dep0_2_0::a::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl FooIndices { + /// Creates a new copy of `FooIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::my::dep0_1_0::a::GuestIndices::new(_component)?; + let interface1 = exports::my::dep0_2_0::a::GuestIndices::new(_component)?; + Ok(FooIndices { + interface0, + interface1, + }) + } + /// Creates a new instance of [`FooIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Foo`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Foo`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::my::dep0_1_0::a::GuestIndices::new_instance( + &mut store, + _instance, + )?; + let interface1 = exports::my::dep0_2_0::a::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(FooIndices { + interface0, + interface1, + }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Foo`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + let interface1 = self.interface1.load(&mut store, &_instance)?; + Ok(Foo { interface0, interface1 }) + } + } + impl Foo { + /// Convenience wrapper around [`FooPre::new`] and + /// [`FooPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + FooPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`FooIndices::new_instance`] and + /// [`FooIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = FooIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + my::dep0_1_0::a::Host + my::dep0_2_0::a::Host + + 'static, + U: Send + my::dep0_1_0::a::Host + my::dep0_2_0::a::Host, + { + my::dep0_1_0::a::add_to_linker(linker, get)?; + my::dep0_2_0::a::add_to_linker(linker, get)?; + Ok(()) + } + pub fn my_dep0_1_0_a(&self) -> &exports::my::dep0_1_0::a::Guest { + &self.interface0 + } + pub fn my_dep0_2_0_a(&self) -> &exports::my::dep0_2_0::a::Guest { + &self.interface1 + } + } +}; +pub mod my { + pub mod dep0_1_0 { + #[allow(clippy::all)] + pub mod a { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn x( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("my:dep/a@0.1.0")?; + inst.func_wrap_concurrent( + "x", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::x(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn x( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::x(store) + } + } + } + } + pub mod dep0_2_0 { + #[allow(clippy::all)] + pub mod a { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn x( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("my:dep/a@0.2.0")?; + inst.func_wrap_concurrent( + "x", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::x(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn x( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::x(store) + } + } + } + } +} +pub mod exports { + pub mod my { + pub mod dep0_1_0 { + #[allow(clippy::all)] + pub mod a { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + x: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + x: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "my:dep/a@0.1.0") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `my:dep/a@0.1.0`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "my:dep/a@0.1.0") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `my:dep/a@0.1.0`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `my:dep/a@0.1.0` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let x = lookup("x")?; + Ok(GuestIndices { x }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let x = *_instance + .get_typed_func::<(), ()>(&mut store, &self.x)? + .func(); + Ok(Guest { x }) + } + } + impl Guest { + pub async fn call_x( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.x) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + } + } + } + pub mod dep0_2_0 { + #[allow(clippy::all)] + pub mod a { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + x: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + x: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "my:dep/a@0.2.0") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `my:dep/a@0.2.0`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "my:dep/a@0.2.0") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `my:dep/a@0.2.0`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `my:dep/a@0.2.0` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let x = lookup("x")?; + Ok(GuestIndices { x }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let x = *_instance + .get_typed_func::<(), ()>(&mut store, &self.x)? + .func(); + Ok(Guest { x }) + } + } + impl Guest { + pub async fn call_x( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.x) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/multiversion_tracing_async.rs b/crates/component-macro/tests/expanded/multiversion_tracing_async.rs index 76256e2fa92b..9aeb377a465e 100644 --- a/crates/component-macro/tests/expanded/multiversion_tracing_async.rs +++ b/crates/component-macro/tests/expanded/multiversion_tracing_async.rs @@ -217,19 +217,23 @@ pub mod my { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -288,19 +292,23 @@ pub mod my { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/path1.rs b/crates/component-macro/tests/expanded/path1.rs index 834a00afedb8..a991592c753e 100644 --- a/crates/component-macro/tests/expanded/path1.rs +++ b/crates/component-macro/tests/expanded/path1.rs @@ -176,19 +176,23 @@ pub mod paths { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("paths:path1/test")?; Ok(()) diff --git a/crates/component-macro/tests/expanded/path1_async.rs b/crates/component-macro/tests/expanded/path1_async.rs index d4b1af2dee6d..6d2c4fdb3b46 100644 --- a/crates/component-macro/tests/expanded/path1_async.rs +++ b/crates/component-macro/tests/expanded/path1_async.rs @@ -184,19 +184,23 @@ pub mod paths { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/path1_concurrent.rs b/crates/component-macro/tests/expanded/path1_concurrent.rs new file mode 100644 index 000000000000..3161aac96263 --- /dev/null +++ b/crates/component-macro/tests/expanded/path1_concurrent.rs @@ -0,0 +1,223 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `path1`. +/// +/// This structure is created through [`Path1Pre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Path1`] as well. +pub struct Path1Pre { + instance_pre: wasmtime::component::InstancePre, + indices: Path1Indices, +} +impl Clone for Path1Pre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> Path1Pre<_T> { + /// Creates a new copy of `Path1Pre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = Path1Indices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Path1`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `path1`. +/// +/// This is an implementation detail of [`Path1Pre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Path1`] as well. +#[derive(Clone)] +pub struct Path1Indices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `path1`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Path1::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`Path1Pre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`Path1Pre::instantiate_async`] to +/// create a [`Path1`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Path1::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`Path1Indices::new_instance`] followed +/// by [`Path1Indices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Path1 {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl Path1Indices { + /// Creates a new copy of `Path1Indices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(Path1Indices {}) + } + /// Creates a new instance of [`Path1Indices`] from an + /// instantiated component. + /// + /// This method of creating a [`Path1`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Path1`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Path1Indices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Path1`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Path1 {}) + } + } + impl Path1 { + /// Convenience wrapper around [`Path1Pre::new`] and + /// [`Path1Pre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + Path1Pre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`Path1Indices::new_instance`] and + /// [`Path1Indices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = Path1Indices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + paths::path1::test::Host + 'static, + U: Send + paths::path1::test::Host, + { + paths::path1::test::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +pub mod paths { + pub mod path1 { + #[allow(clippy::all)] + pub mod test { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("paths:path1/test")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} diff --git a/crates/component-macro/tests/expanded/path1_tracing_async.rs b/crates/component-macro/tests/expanded/path1_tracing_async.rs index d4b1af2dee6d..6d2c4fdb3b46 100644 --- a/crates/component-macro/tests/expanded/path1_tracing_async.rs +++ b/crates/component-macro/tests/expanded/path1_tracing_async.rs @@ -184,19 +184,23 @@ pub mod paths { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/path2.rs b/crates/component-macro/tests/expanded/path2.rs index fd9b5460a9e8..cbafd8fe984f 100644 --- a/crates/component-macro/tests/expanded/path2.rs +++ b/crates/component-macro/tests/expanded/path2.rs @@ -176,19 +176,23 @@ pub mod paths { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("paths:path2/test")?; Ok(()) diff --git a/crates/component-macro/tests/expanded/path2_async.rs b/crates/component-macro/tests/expanded/path2_async.rs index 45fdb5d811b5..e726c8bb0356 100644 --- a/crates/component-macro/tests/expanded/path2_async.rs +++ b/crates/component-macro/tests/expanded/path2_async.rs @@ -184,19 +184,23 @@ pub mod paths { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/path2_concurrent.rs b/crates/component-macro/tests/expanded/path2_concurrent.rs new file mode 100644 index 000000000000..d5d1dd82597f --- /dev/null +++ b/crates/component-macro/tests/expanded/path2_concurrent.rs @@ -0,0 +1,223 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `path2`. +/// +/// This structure is created through [`Path2Pre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Path2`] as well. +pub struct Path2Pre { + instance_pre: wasmtime::component::InstancePre, + indices: Path2Indices, +} +impl Clone for Path2Pre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> Path2Pre<_T> { + /// Creates a new copy of `Path2Pre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = Path2Indices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Path2`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `path2`. +/// +/// This is an implementation detail of [`Path2Pre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Path2`] as well. +#[derive(Clone)] +pub struct Path2Indices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `path2`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Path2::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`Path2Pre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`Path2Pre::instantiate_async`] to +/// create a [`Path2`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Path2::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`Path2Indices::new_instance`] followed +/// by [`Path2Indices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Path2 {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl Path2Indices { + /// Creates a new copy of `Path2Indices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(Path2Indices {}) + } + /// Creates a new instance of [`Path2Indices`] from an + /// instantiated component. + /// + /// This method of creating a [`Path2`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Path2`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Path2Indices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Path2`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Path2 {}) + } + } + impl Path2 { + /// Convenience wrapper around [`Path2Pre::new`] and + /// [`Path2Pre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + Path2Pre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`Path2Indices::new_instance`] and + /// [`Path2Indices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = Path2Indices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + paths::path2::test::Host + 'static, + U: Send + paths::path2::test::Host, + { + paths::path2::test::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +pub mod paths { + pub mod path2 { + #[allow(clippy::all)] + pub mod test { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("paths:path2/test")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} diff --git a/crates/component-macro/tests/expanded/path2_tracing_async.rs b/crates/component-macro/tests/expanded/path2_tracing_async.rs index 45fdb5d811b5..e726c8bb0356 100644 --- a/crates/component-macro/tests/expanded/path2_tracing_async.rs +++ b/crates/component-macro/tests/expanded/path2_tracing_async.rs @@ -184,19 +184,23 @@ pub mod paths { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/records.rs b/crates/component-macro/tests/expanded/records.rs index edca81d63efb..516c0a43a54a 100644 --- a/crates/component-macro/tests/expanded/records.rs +++ b/crates/component-macro/tests/expanded/records.rs @@ -347,19 +347,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/records")?; inst.func_wrap( @@ -893,7 +897,10 @@ pub mod exports { &self, mut store: S, arg0: (char, u32), - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< ((char, u32),), @@ -907,7 +914,10 @@ pub mod exports { pub fn call_tuple_result( &self, mut store: S, - ) -> wasmtime::Result<(char, u32)> { + ) -> wasmtime::Result<(char, u32)> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -922,7 +932,10 @@ pub mod exports { &self, mut store: S, arg0: Empty, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Empty,), @@ -936,7 +949,10 @@ pub mod exports { pub fn call_empty_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -951,7 +967,10 @@ pub mod exports { &self, mut store: S, arg0: Scalars, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Scalars,), @@ -965,7 +984,10 @@ pub mod exports { pub fn call_scalar_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -980,7 +1002,10 @@ pub mod exports { &self, mut store: S, arg0: ReallyFlags, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (ReallyFlags,), @@ -994,7 +1019,10 @@ pub mod exports { pub fn call_flags_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1009,7 +1037,10 @@ pub mod exports { &self, mut store: S, arg0: &Aggregates, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&Aggregates,), @@ -1023,7 +1054,10 @@ pub mod exports { pub fn call_aggregate_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1038,7 +1072,10 @@ pub mod exports { &self, mut store: S, arg0: TupleTypedef2, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (TupleTypedef2,), diff --git a/crates/component-macro/tests/expanded/records_async.rs b/crates/component-macro/tests/expanded/records_async.rs index 0c087de7ff66..baa76ecd663d 100644 --- a/crates/component-macro/tests/expanded/records_async.rs +++ b/crates/component-macro/tests/expanded/records_async.rs @@ -355,19 +355,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/records_concurrent.rs b/crates/component-macro/tests/expanded/records_concurrent.rs new file mode 100644 index 000000000000..b7a90729ab43 --- /dev/null +++ b/crates/component-macro/tests/expanded/records_concurrent.rs @@ -0,0 +1,1558 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::records::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::records::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::records::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::records::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::records::Host + 'static, + U: Send + foo::foo::records::Host, + { + foo::foo::records::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_records(&self) -> &exports::foo::foo::records::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod records { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct Empty {} + impl core::fmt::Debug for Empty { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Empty").finish() + } + } + const _: () = { + assert!(0 == < Empty as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Empty as wasmtime::component::ComponentType >::ALIGN32); + }; + /// A record containing two scalar fields + /// that both have the same type + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct Scalars { + /// The first field, named a + #[component(name = "a")] + pub a: u32, + /// The second field, named b + #[component(name = "b")] + pub b: u32, + } + impl core::fmt::Debug for Scalars { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Scalars") + .field("a", &self.a) + .field("b", &self.b) + .finish() + } + } + const _: () = { + assert!(8 == < Scalars as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Scalars as wasmtime::component::ComponentType >::ALIGN32); + }; + /// A record that is really just flags + /// All of the fields are bool + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct ReallyFlags { + #[component(name = "a")] + pub a: bool, + #[component(name = "b")] + pub b: bool, + #[component(name = "c")] + pub c: bool, + #[component(name = "d")] + pub d: bool, + #[component(name = "e")] + pub e: bool, + #[component(name = "f")] + pub f: bool, + #[component(name = "g")] + pub g: bool, + #[component(name = "h")] + pub h: bool, + #[component(name = "i")] + pub i: bool, + } + impl core::fmt::Debug for ReallyFlags { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("ReallyFlags") + .field("a", &self.a) + .field("b", &self.b) + .field("c", &self.c) + .field("d", &self.d) + .field("e", &self.e) + .field("f", &self.f) + .field("g", &self.g) + .field("h", &self.h) + .field("i", &self.i) + .finish() + } + } + const _: () = { + assert!( + 9 == < ReallyFlags as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < ReallyFlags as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct Aggregates { + #[component(name = "a")] + pub a: Scalars, + #[component(name = "b")] + pub b: u32, + #[component(name = "c")] + pub c: Empty, + #[component(name = "d")] + pub d: wasmtime::component::__internal::String, + #[component(name = "e")] + pub e: ReallyFlags, + } + impl core::fmt::Debug for Aggregates { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Aggregates") + .field("a", &self.a) + .field("b", &self.b) + .field("c", &self.c) + .field("d", &self.d) + .field("e", &self.e) + .finish() + } + } + const _: () = { + assert!( + 32 == < Aggregates as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < Aggregates as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub type IntTypedef = i32; + const _: () = { + assert!( + 4 == < IntTypedef as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < IntTypedef as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub type TupleTypedef2 = (IntTypedef,); + const _: () = { + assert!( + 4 == < TupleTypedef2 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < TupleTypedef2 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub trait Host { + type Data; + fn tuple_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: (char, u32), + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn tuple_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (char, u32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn empty_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Empty, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn empty_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Empty + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn scalar_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Scalars, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn scalar_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Scalars + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn flags_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: ReallyFlags, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn flags_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ReallyFlags + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn aggregate_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Aggregates, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn aggregate_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Aggregates + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn typedef_inout( + store: wasmtime::StoreContextMut<'_, Self::Data>, + e: TupleTypedef2, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/records")?; + inst.func_wrap_concurrent( + "tuple-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): ((char, u32),)| + { + let host = caller; + let r = ::tuple_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "tuple-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::tuple_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((char, u32),)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((char, u32),)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "empty-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Empty,)| + { + let host = caller; + let r = ::empty_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "empty-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::empty_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Empty,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Empty,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "scalar-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Scalars,)| + { + let host = caller; + let r = ::scalar_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "scalar-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::scalar_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Scalars,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Scalars,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "flags-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (ReallyFlags,)| + { + let host = caller; + let r = ::flags_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "flags-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::flags_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(ReallyFlags,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(ReallyFlags,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "aggregate-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Aggregates,)| + { + let host = caller; + let r = ::aggregate_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "aggregate-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::aggregate_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Aggregates,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Aggregates,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "typedef-inout", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (TupleTypedef2,)| + { + let host = caller; + let r = ::typedef_inout(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(i32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn tuple_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: (char, u32), + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::tuple_arg(store, x) + } + fn tuple_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (char, u32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::tuple_result(store) + } + fn empty_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Empty, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::empty_arg(store, x) + } + fn empty_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Empty + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::empty_result(store) + } + fn scalar_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Scalars, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::scalar_arg(store, x) + } + fn scalar_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Scalars + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::scalar_result(store) + } + fn flags_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: ReallyFlags, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::flags_arg(store, x) + } + fn flags_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ReallyFlags + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::flags_result(store) + } + fn aggregate_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Aggregates, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::aggregate_arg(store, x) + } + fn aggregate_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Aggregates + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::aggregate_result(store) + } + fn typedef_inout( + store: wasmtime::StoreContextMut<'_, Self::Data>, + e: TupleTypedef2, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> i32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::typedef_inout(store, e) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod records { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct Empty {} + impl core::fmt::Debug for Empty { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("Empty").finish() + } + } + const _: () = { + assert!( + 0 == < Empty as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < Empty as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + /// A record containing two scalar fields + /// that both have the same type + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct Scalars { + /// The first field, named a + #[component(name = "a")] + pub a: u32, + /// The second field, named b + #[component(name = "b")] + pub b: u32, + } + impl core::fmt::Debug for Scalars { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("Scalars") + .field("a", &self.a) + .field("b", &self.b) + .finish() + } + } + const _: () = { + assert!( + 8 == < Scalars as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < Scalars as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + /// A record that is really just flags + /// All of the fields are bool + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct ReallyFlags { + #[component(name = "a")] + pub a: bool, + #[component(name = "b")] + pub b: bool, + #[component(name = "c")] + pub c: bool, + #[component(name = "d")] + pub d: bool, + #[component(name = "e")] + pub e: bool, + #[component(name = "f")] + pub f: bool, + #[component(name = "g")] + pub g: bool, + #[component(name = "h")] + pub h: bool, + #[component(name = "i")] + pub i: bool, + } + impl core::fmt::Debug for ReallyFlags { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("ReallyFlags") + .field("a", &self.a) + .field("b", &self.b) + .field("c", &self.c) + .field("d", &self.d) + .field("e", &self.e) + .field("f", &self.f) + .field("g", &self.g) + .field("h", &self.h) + .field("i", &self.i) + .finish() + } + } + const _: () = { + assert!( + 9 == < ReallyFlags as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 1 == < ReallyFlags as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct Aggregates { + #[component(name = "a")] + pub a: Scalars, + #[component(name = "b")] + pub b: u32, + #[component(name = "c")] + pub c: Empty, + #[component(name = "d")] + pub d: wasmtime::component::__internal::String, + #[component(name = "e")] + pub e: ReallyFlags, + } + impl core::fmt::Debug for Aggregates { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("Aggregates") + .field("a", &self.a) + .field("b", &self.b) + .field("c", &self.c) + .field("d", &self.d) + .field("e", &self.e) + .finish() + } + } + const _: () = { + assert!( + 32 == < Aggregates as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 4 == < Aggregates as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub type IntTypedef = i32; + const _: () = { + assert!( + 4 == < IntTypedef as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < IntTypedef as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub type TupleTypedef2 = (IntTypedef,); + const _: () = { + assert!( + 4 == < TupleTypedef2 as wasmtime::component::ComponentType + >::SIZE32 + ); + assert!( + 4 == < TupleTypedef2 as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + pub struct Guest { + tuple_arg: wasmtime::component::Func, + tuple_result: wasmtime::component::Func, + empty_arg: wasmtime::component::Func, + empty_result: wasmtime::component::Func, + scalar_arg: wasmtime::component::Func, + scalar_result: wasmtime::component::Func, + flags_arg: wasmtime::component::Func, + flags_result: wasmtime::component::Func, + aggregate_arg: wasmtime::component::Func, + aggregate_result: wasmtime::component::Func, + typedef_inout: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + tuple_arg: wasmtime::component::ComponentExportIndex, + tuple_result: wasmtime::component::ComponentExportIndex, + empty_arg: wasmtime::component::ComponentExportIndex, + empty_result: wasmtime::component::ComponentExportIndex, + scalar_arg: wasmtime::component::ComponentExportIndex, + scalar_result: wasmtime::component::ComponentExportIndex, + flags_arg: wasmtime::component::ComponentExportIndex, + flags_result: wasmtime::component::ComponentExportIndex, + aggregate_arg: wasmtime::component::ComponentExportIndex, + aggregate_result: wasmtime::component::ComponentExportIndex, + typedef_inout: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/records") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/records`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/records") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/records`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/records` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let tuple_arg = lookup("tuple-arg")?; + let tuple_result = lookup("tuple-result")?; + let empty_arg = lookup("empty-arg")?; + let empty_result = lookup("empty-result")?; + let scalar_arg = lookup("scalar-arg")?; + let scalar_result = lookup("scalar-result")?; + let flags_arg = lookup("flags-arg")?; + let flags_result = lookup("flags-result")?; + let aggregate_arg = lookup("aggregate-arg")?; + let aggregate_result = lookup("aggregate-result")?; + let typedef_inout = lookup("typedef-inout")?; + Ok(GuestIndices { + tuple_arg, + tuple_result, + empty_arg, + empty_result, + scalar_arg, + scalar_result, + flags_arg, + flags_result, + aggregate_arg, + aggregate_result, + typedef_inout, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let tuple_arg = *_instance + .get_typed_func::< + ((char, u32),), + (), + >(&mut store, &self.tuple_arg)? + .func(); + let tuple_result = *_instance + .get_typed_func::< + (), + ((char, u32),), + >(&mut store, &self.tuple_result)? + .func(); + let empty_arg = *_instance + .get_typed_func::<(Empty,), ()>(&mut store, &self.empty_arg)? + .func(); + let empty_result = *_instance + .get_typed_func::< + (), + (Empty,), + >(&mut store, &self.empty_result)? + .func(); + let scalar_arg = *_instance + .get_typed_func::< + (Scalars,), + (), + >(&mut store, &self.scalar_arg)? + .func(); + let scalar_result = *_instance + .get_typed_func::< + (), + (Scalars,), + >(&mut store, &self.scalar_result)? + .func(); + let flags_arg = *_instance + .get_typed_func::< + (ReallyFlags,), + (), + >(&mut store, &self.flags_arg)? + .func(); + let flags_result = *_instance + .get_typed_func::< + (), + (ReallyFlags,), + >(&mut store, &self.flags_result)? + .func(); + let aggregate_arg = *_instance + .get_typed_func::< + (&Aggregates,), + (), + >(&mut store, &self.aggregate_arg)? + .func(); + let aggregate_result = *_instance + .get_typed_func::< + (), + (Aggregates,), + >(&mut store, &self.aggregate_result)? + .func(); + let typedef_inout = *_instance + .get_typed_func::< + (TupleTypedef2,), + (i32,), + >(&mut store, &self.typedef_inout)? + .func(); + Ok(Guest { + tuple_arg, + tuple_result, + empty_arg, + empty_result, + scalar_arg, + scalar_result, + flags_arg, + flags_result, + aggregate_arg, + aggregate_result, + typedef_inout, + }) + } + } + impl Guest { + pub async fn call_tuple_arg( + &self, + mut store: S, + arg0: (char, u32), + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ((char, u32),), + (), + >::new_unchecked(self.tuple_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_tuple_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + ((char, u32),), + >::new_unchecked(self.tuple_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_empty_arg( + &self, + mut store: S, + arg0: Empty, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Empty,), + (), + >::new_unchecked(self.empty_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_empty_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Empty,), + >::new_unchecked(self.empty_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_scalar_arg( + &self, + mut store: S, + arg0: Scalars, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Scalars,), + (), + >::new_unchecked(self.scalar_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_scalar_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Scalars,), + >::new_unchecked(self.scalar_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_flags_arg( + &self, + mut store: S, + arg0: ReallyFlags, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (ReallyFlags,), + (), + >::new_unchecked(self.flags_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_flags_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (ReallyFlags,), + >::new_unchecked(self.flags_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_aggregate_arg( + &self, + mut store: S, + arg0: Aggregates, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Aggregates,), + (), + >::new_unchecked(self.aggregate_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_aggregate_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Aggregates,), + >::new_unchecked(self.aggregate_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_typedef_inout( + &self, + mut store: S, + arg0: TupleTypedef2, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (TupleTypedef2,), + (i32,), + >::new_unchecked(self.typedef_inout) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/records_tracing_async.rs b/crates/component-macro/tests/expanded/records_tracing_async.rs index 075b7dc57ae1..160bd8cf7b25 100644 --- a/crates/component-macro/tests/expanded/records_tracing_async.rs +++ b/crates/component-macro/tests/expanded/records_tracing_async.rs @@ -355,19 +355,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/rename.rs b/crates/component-macro/tests/expanded/rename.rs index 5870b202254f..65b7b4344bf7 100644 --- a/crates/component-macro/tests/expanded/rename.rs +++ b/crates/component-macro/tests/expanded/rename.rs @@ -182,19 +182,23 @@ pub mod foo { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/green")?; Ok(()) @@ -224,19 +228,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/red")?; inst.func_wrap( diff --git a/crates/component-macro/tests/expanded/rename_async.rs b/crates/component-macro/tests/expanded/rename_async.rs index 467bb6509fb6..96522907ae3e 100644 --- a/crates/component-macro/tests/expanded/rename_async.rs +++ b/crates/component-macro/tests/expanded/rename_async.rs @@ -190,19 +190,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -237,19 +241,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/rename_concurrent.rs b/crates/component-macro/tests/expanded/rename_concurrent.rs new file mode 100644 index 000000000000..1b395b24eeb4 --- /dev/null +++ b/crates/component-macro/tests/expanded/rename_concurrent.rs @@ -0,0 +1,332 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `neptune`. +/// +/// This structure is created through [`NeptunePre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Neptune`] as well. +pub struct NeptunePre { + instance_pre: wasmtime::component::InstancePre, + indices: NeptuneIndices, +} +impl Clone for NeptunePre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> NeptunePre<_T> { + /// Creates a new copy of `NeptunePre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = NeptuneIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Neptune`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `neptune`. +/// +/// This is an implementation detail of [`NeptunePre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Neptune`] as well. +#[derive(Clone)] +pub struct NeptuneIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `neptune`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Neptune::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`NeptunePre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`NeptunePre::instantiate_async`] to +/// create a [`Neptune`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Neptune::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`NeptuneIndices::new_instance`] followed +/// by [`NeptuneIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Neptune {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl NeptuneIndices { + /// Creates a new copy of `NeptuneIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(NeptuneIndices {}) + } + /// Creates a new instance of [`NeptuneIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Neptune`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Neptune`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(NeptuneIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Neptune`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Neptune {}) + } + } + impl Neptune { + /// Convenience wrapper around [`NeptunePre::new`] and + /// [`NeptunePre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + NeptunePre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`NeptuneIndices::new_instance`] and + /// [`NeptuneIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = NeptuneIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::green::Host + foo::foo::red::Host + 'static, + U: Send + foo::foo::green::Host + foo::foo::red::Host, + { + foo::foo::green::add_to_linker(linker, get)?; + foo::foo::red::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod green { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Thing = i32; + const _: () = { + assert!(4 == < Thing as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Thing as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/green")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + #[allow(clippy::all)] + pub mod red { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Thing = super::super::super::foo::foo::green::Thing; + const _: () = { + assert!(4 == < Thing as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Thing as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Thing + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/red")?; + inst.func_wrap_concurrent( + "foo", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::foo(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Thing,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Thing,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Thing + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::foo(store) + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/rename_tracing_async.rs b/crates/component-macro/tests/expanded/rename_tracing_async.rs index 2adc67f4420c..a7641fca9f4a 100644 --- a/crates/component-macro/tests/expanded/rename_tracing_async.rs +++ b/crates/component-macro/tests/expanded/rename_tracing_async.rs @@ -190,19 +190,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -237,19 +241,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/resources-export.rs b/crates/component-macro/tests/expanded/resources-export.rs index 4414d8344ee2..cd7a7f94877f 100644 --- a/crates/component-macro/tests/expanded/resources-export.rs +++ b/crates/component-macro/tests/expanded/resources-export.rs @@ -249,7 +249,7 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::{anyhow, Box}; pub enum Y {} - pub trait HostY { + pub trait HostY: Sized { fn drop( &mut self, rep: wasmtime::component::Resource, @@ -263,22 +263,26 @@ pub mod foo { HostY::drop(*self, rep) } } - pub trait Host: HostY {} + pub trait Host: HostY + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/transitive-import")?; inst.resource( @@ -432,7 +436,10 @@ pub mod exports { pub fn call_constructor( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -446,7 +453,10 @@ pub mod exports { pub fn call_static_a( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -461,7 +471,10 @@ pub mod exports { &self, mut store: S, arg0: wasmtime::component::ResourceAny, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (wasmtime::component::ResourceAny,), @@ -602,7 +615,10 @@ pub mod exports { &self, mut store: S, arg0: wasmtime::component::Resource, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (wasmtime::component::Resource,), @@ -616,7 +632,10 @@ pub mod exports { pub fn call_static_a( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -632,7 +651,10 @@ pub mod exports { mut store: S, arg0: wasmtime::component::ResourceAny, arg1: wasmtime::component::Resource, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< ( @@ -747,7 +769,10 @@ pub mod exports { pub fn call_constructor( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -861,7 +886,10 @@ pub mod exports { &self, mut store: S, arg0: wasmtime::component::ResourceAny, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (wasmtime::component::ResourceAny,), diff --git a/crates/component-macro/tests/expanded/resources-export_async.rs b/crates/component-macro/tests/expanded/resources-export_async.rs index 9a37b5488e67..f71deb5ee997 100644 --- a/crates/component-macro/tests/expanded/resources-export_async.rs +++ b/crates/component-macro/tests/expanded/resources-export_async.rs @@ -257,7 +257,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum Y {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostY { + pub trait HostY: Sized { async fn drop( &mut self, rep: wasmtime::component::Resource, @@ -272,22 +272,26 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostY {} + pub trait Host: Send + HostY + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/resources-export_concurrent.rs b/crates/component-macro/tests/expanded/resources-export_concurrent.rs new file mode 100644 index 000000000000..a1405a642102 --- /dev/null +++ b/crates/component-macro/tests/expanded/resources-export_concurrent.rs @@ -0,0 +1,938 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `w`. +/// +/// This structure is created through [`WPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`W`] as well. +pub struct WPre { + instance_pre: wasmtime::component::InstancePre, + indices: WIndices, +} +impl Clone for WPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> WPre<_T> { + /// Creates a new copy of `WPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = WIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`W`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `w`. +/// +/// This is an implementation detail of [`WPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`W`] as well. +#[derive(Clone)] +pub struct WIndices { + interface0: exports::foo::foo::simple_export::GuestIndices, + interface1: exports::foo::foo::export_using_import::GuestIndices, + interface2: exports::foo::foo::export_using_export1::GuestIndices, + interface3: exports::foo::foo::export_using_export2::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `w`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`W::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`WPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`WPre::instantiate_async`] to +/// create a [`W`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`W::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`WIndices::new_instance`] followed +/// by [`WIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct W { + interface0: exports::foo::foo::simple_export::Guest, + interface1: exports::foo::foo::export_using_import::Guest, + interface2: exports::foo::foo::export_using_export1::Guest, + interface3: exports::foo::foo::export_using_export2::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl WIndices { + /// Creates a new copy of `WIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::simple_export::GuestIndices::new( + _component, + )?; + let interface1 = exports::foo::foo::export_using_import::GuestIndices::new( + _component, + )?; + let interface2 = exports::foo::foo::export_using_export1::GuestIndices::new( + _component, + )?; + let interface3 = exports::foo::foo::export_using_export2::GuestIndices::new( + _component, + )?; + Ok(WIndices { + interface0, + interface1, + interface2, + interface3, + }) + } + /// Creates a new instance of [`WIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`W`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`W`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::simple_export::GuestIndices::new_instance( + &mut store, + _instance, + )?; + let interface1 = exports::foo::foo::export_using_import::GuestIndices::new_instance( + &mut store, + _instance, + )?; + let interface2 = exports::foo::foo::export_using_export1::GuestIndices::new_instance( + &mut store, + _instance, + )?; + let interface3 = exports::foo::foo::export_using_export2::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(WIndices { + interface0, + interface1, + interface2, + interface3, + }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`W`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + let interface1 = self.interface1.load(&mut store, &_instance)?; + let interface2 = self.interface2.load(&mut store, &_instance)?; + let interface3 = self.interface3.load(&mut store, &_instance)?; + Ok(W { + interface0, + interface1, + interface2, + interface3, + }) + } + } + impl W { + /// Convenience wrapper around [`WPre::new`] and + /// [`WPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + WPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`WIndices::new_instance`] and + /// [`WIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = WIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::transitive_import::Host + 'static, + U: Send + foo::foo::transitive_import::Host, + { + foo::foo::transitive_import::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_simple_export(&self) -> &exports::foo::foo::simple_export::Guest { + &self.interface0 + } + pub fn foo_foo_export_using_import( + &self, + ) -> &exports::foo::foo::export_using_import::Guest { + &self.interface1 + } + pub fn foo_foo_export_using_export1( + &self, + ) -> &exports::foo::foo::export_using_export1::Guest { + &self.interface2 + } + pub fn foo_foo_export_using_export2( + &self, + ) -> &exports::foo::foo::export_using_export2::Guest { + &self.interface3 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod transitive_import { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub enum Y {} + pub trait HostY: Sized { + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()>; + } + impl<_T: HostY + ?Sized> HostY for &mut _T { + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + HostY::drop(*self, rep) + } + } + pub trait Host: HostY + Sized {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/transitive-import")?; + inst.resource( + "y", + wasmtime::component::ResourceType::host::(), + move |mut store, rep| -> wasmtime::Result<()> { + HostY::drop( + &mut host_getter(store.data_mut()), + wasmtime::component::Resource::new_own(rep), + ) + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod simple_export { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type A = wasmtime::component::ResourceAny; + pub struct GuestA<'a> { + funcs: &'a Guest, + } + pub struct Guest { + constructor_a_constructor: wasmtime::component::Func, + static_a_static_a: wasmtime::component::Func, + method_a_method_a: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + constructor_a_constructor: wasmtime::component::ComponentExportIndex, + static_a_static_a: wasmtime::component::ComponentExportIndex, + method_a_method_a: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/simple-export") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/simple-export`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/simple-export") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/simple-export`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/simple-export` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let constructor_a_constructor = lookup("[constructor]a")?; + let static_a_static_a = lookup("[static]a.static-a")?; + let method_a_method_a = lookup("[method]a.method-a")?; + Ok(GuestIndices { + constructor_a_constructor, + static_a_static_a, + method_a_method_a, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let constructor_a_constructor = *_instance + .get_typed_func::< + (), + (wasmtime::component::ResourceAny,), + >(&mut store, &self.constructor_a_constructor)? + .func(); + let static_a_static_a = *_instance + .get_typed_func::< + (), + (u32,), + >(&mut store, &self.static_a_static_a)? + .func(); + let method_a_method_a = *_instance + .get_typed_func::< + (wasmtime::component::ResourceAny,), + (u32,), + >(&mut store, &self.method_a_method_a)? + .func(); + Ok(Guest { + constructor_a_constructor, + static_a_static_a, + method_a_method_a, + }) + } + } + impl Guest { + pub fn a(&self) -> GuestA<'_> { + GuestA { funcs: self } + } + } + impl GuestA<'_> { + pub async fn call_constructor( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::ResourceAny,), + >::new_unchecked(self.funcs.constructor_a_constructor) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_static_a( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u32,), + >::new_unchecked(self.funcs.static_a_static_a) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_method_a( + &self, + mut store: S, + arg0: wasmtime::component::ResourceAny, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::ResourceAny,), + (u32,), + >::new_unchecked(self.funcs.method_a_method_a) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + #[allow(clippy::all)] + pub mod export_using_import { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Y = super::super::super::super::foo::foo::transitive_import::Y; + pub type A = wasmtime::component::ResourceAny; + pub struct GuestA<'a> { + funcs: &'a Guest, + } + pub struct Guest { + constructor_a_constructor: wasmtime::component::Func, + static_a_static_a: wasmtime::component::Func, + method_a_method_a: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + constructor_a_constructor: wasmtime::component::ComponentExportIndex, + static_a_static_a: wasmtime::component::ComponentExportIndex, + method_a_method_a: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/export-using-import") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/export-using-import`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/export-using-import") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/export-using-import`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/export-using-import` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let constructor_a_constructor = lookup("[constructor]a")?; + let static_a_static_a = lookup("[static]a.static-a")?; + let method_a_method_a = lookup("[method]a.method-a")?; + Ok(GuestIndices { + constructor_a_constructor, + static_a_static_a, + method_a_method_a, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let constructor_a_constructor = *_instance + .get_typed_func::< + (wasmtime::component::Resource,), + (wasmtime::component::ResourceAny,), + >(&mut store, &self.constructor_a_constructor)? + .func(); + let static_a_static_a = *_instance + .get_typed_func::< + (), + (wasmtime::component::Resource,), + >(&mut store, &self.static_a_static_a)? + .func(); + let method_a_method_a = *_instance + .get_typed_func::< + ( + wasmtime::component::ResourceAny, + wasmtime::component::Resource, + ), + (wasmtime::component::Resource,), + >(&mut store, &self.method_a_method_a)? + .func(); + Ok(Guest { + constructor_a_constructor, + static_a_static_a, + method_a_method_a, + }) + } + } + impl Guest { + pub fn a(&self) -> GuestA<'_> { + GuestA { funcs: self } + } + } + impl GuestA<'_> { + pub async fn call_constructor( + &self, + mut store: S, + arg0: wasmtime::component::Resource, + ) -> wasmtime::Result< + wasmtime::component::Promise, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::Resource,), + (wasmtime::component::ResourceAny,), + >::new_unchecked(self.funcs.constructor_a_constructor) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_static_a( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::Resource,), + >::new_unchecked(self.funcs.static_a_static_a) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_method_a( + &self, + mut store: S, + arg0: wasmtime::component::ResourceAny, + arg1: wasmtime::component::Resource, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + wasmtime::component::ResourceAny, + wasmtime::component::Resource, + ), + (wasmtime::component::Resource,), + >::new_unchecked(self.funcs.method_a_method_a) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0, arg1)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + #[allow(clippy::all)] + pub mod export_using_export1 { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type A = wasmtime::component::ResourceAny; + pub struct GuestA<'a> { + funcs: &'a Guest, + } + pub struct Guest { + constructor_a_constructor: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + constructor_a_constructor: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/export-using-export1") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/export-using-export1`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/export-using-export1") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/export-using-export1`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/export-using-export1` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let constructor_a_constructor = lookup("[constructor]a")?; + Ok(GuestIndices { + constructor_a_constructor, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let constructor_a_constructor = *_instance + .get_typed_func::< + (), + (wasmtime::component::ResourceAny,), + >(&mut store, &self.constructor_a_constructor)? + .func(); + Ok(Guest { constructor_a_constructor }) + } + } + impl Guest { + pub fn a(&self) -> GuestA<'_> { + GuestA { funcs: self } + } + } + impl GuestA<'_> { + pub async fn call_constructor( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::ResourceAny,), + >::new_unchecked(self.funcs.constructor_a_constructor) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + #[allow(clippy::all)] + pub mod export_using_export2 { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type A = super::super::super::super::exports::foo::foo::export_using_export1::A; + pub type B = wasmtime::component::ResourceAny; + pub struct GuestB<'a> { + funcs: &'a Guest, + } + pub struct Guest { + constructor_b_constructor: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + constructor_b_constructor: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/export-using-export2") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/export-using-export2`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/export-using-export2") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/export-using-export2`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/export-using-export2` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let constructor_b_constructor = lookup("[constructor]b")?; + Ok(GuestIndices { + constructor_b_constructor, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let constructor_b_constructor = *_instance + .get_typed_func::< + (wasmtime::component::ResourceAny,), + (wasmtime::component::ResourceAny,), + >(&mut store, &self.constructor_b_constructor)? + .func(); + Ok(Guest { constructor_b_constructor }) + } + } + impl Guest { + pub fn b(&self) -> GuestB<'_> { + GuestB { funcs: self } + } + } + impl GuestB<'_> { + pub async fn call_constructor( + &self, + mut store: S, + arg0: wasmtime::component::ResourceAny, + ) -> wasmtime::Result< + wasmtime::component::Promise, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::ResourceAny,), + (wasmtime::component::ResourceAny,), + >::new_unchecked(self.funcs.constructor_b_constructor) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/resources-export_tracing_async.rs b/crates/component-macro/tests/expanded/resources-export_tracing_async.rs index 7cf0ade0f577..8ee732626b02 100644 --- a/crates/component-macro/tests/expanded/resources-export_tracing_async.rs +++ b/crates/component-macro/tests/expanded/resources-export_tracing_async.rs @@ -257,7 +257,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum Y {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostY { + pub trait HostY: Sized { async fn drop( &mut self, rep: wasmtime::component::Resource, @@ -272,22 +272,26 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostY {} + pub trait Host: Send + HostY + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/resources-import.rs b/crates/component-macro/tests/expanded/resources-import.rs index cd27d777f581..05352420abe5 100644 --- a/crates/component-macro/tests/expanded/resources-import.rs +++ b/crates/component-macro/tests/expanded/resources-import.rs @@ -1,5 +1,5 @@ pub enum WorldResource {} -pub trait HostWorldResource { +pub trait HostWorldResource: Sized { fn new(&mut self) -> wasmtime::component::Resource; fn foo(&mut self, self_: wasmtime::component::Resource) -> (); fn static_foo(&mut self) -> (); @@ -130,10 +130,11 @@ pub trait TheWorldImports: HostWorldResource { } pub trait TheWorldImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: TheWorldImports; } -impl TheWorldImportsGetHost for F +impl TheWorldImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: TheWorldImports, @@ -242,9 +243,12 @@ const _: () = { let indices = TheWorldIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost<&'a mut T, T, Host: TheWorldImports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> TheWorldImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut linker = linker.root(); linker @@ -321,7 +325,10 @@ const _: () = { pub fn call_some_world_func2( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -346,7 +353,7 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::{anyhow, Box}; pub enum Bar {} - pub trait HostBar { + pub trait HostBar: Sized { fn new(&mut self) -> wasmtime::component::Resource; fn static_a(&mut self) -> u32; fn method_a(&mut self, self_: wasmtime::component::Resource) -> u32; @@ -430,7 +437,7 @@ pub mod foo { 4 == < SomeHandle as wasmtime::component::ComponentType >::ALIGN32 ); }; - pub trait Host: HostBar { + pub trait Host: HostBar + Sized { fn bar_own_arg(&mut self, x: wasmtime::component::Resource) -> (); fn bar_borrow_arg( &mut self, @@ -492,19 +499,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/resources")?; inst.resource( @@ -862,7 +873,7 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::{anyhow, Box}; pub enum A {} - pub trait HostA { + pub trait HostA: Sized { fn drop( &mut self, rep: wasmtime::component::Resource, @@ -876,22 +887,26 @@ pub mod foo { HostA::drop(*self, rep) } } - pub trait Host: HostA {} + pub trait Host: HostA + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/long-use-chain1")?; inst.resource( @@ -925,19 +940,23 @@ pub mod foo { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/long-use-chain2")?; Ok(()) @@ -961,19 +980,23 @@ pub mod foo { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/long-use-chain3")?; Ok(()) @@ -999,19 +1022,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/long-use-chain4")?; inst.func_wrap( @@ -1044,7 +1071,7 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::{anyhow, Box}; pub enum Foo {} - pub trait HostFoo { + pub trait HostFoo: Sized { fn drop( &mut self, rep: wasmtime::component::Resource, @@ -1058,22 +1085,26 @@ pub mod foo { HostFoo::drop(*self, rep) } } - pub trait Host: HostFoo {} + pub trait Host: HostFoo + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker .instance("foo:foo/transitive-interface-with-resource")?; @@ -1199,7 +1230,10 @@ pub mod exports { &self, mut store: S, arg0: wasmtime::component::Resource, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (wasmtime::component::Resource,), diff --git a/crates/component-macro/tests/expanded/resources-import_async.rs b/crates/component-macro/tests/expanded/resources-import_async.rs index 99899d3254fc..7b876dff72da 100644 --- a/crates/component-macro/tests/expanded/resources-import_async.rs +++ b/crates/component-macro/tests/expanded/resources-import_async.rs @@ -1,6 +1,6 @@ pub enum WorldResource {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] -pub trait HostWorldResource { +pub trait HostWorldResource: Sized { async fn new(&mut self) -> wasmtime::component::Resource; async fn foo(&mut self, self_: wasmtime::component::Resource) -> (); async fn static_foo(&mut self) -> (); @@ -135,10 +135,11 @@ pub trait TheWorldImports: Send + HostWorldResource { } pub trait TheWorldImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: TheWorldImports; } -impl TheWorldImportsGetHost for F +impl TheWorldImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: TheWorldImports, @@ -250,9 +251,12 @@ const _: () = { let indices = TheWorldIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost<&'a mut T, T, Host: TheWorldImports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> TheWorldImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -374,7 +378,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum Bar {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostBar { + pub trait HostBar: Sized { async fn new(&mut self) -> wasmtime::component::Resource; async fn static_a(&mut self) -> u32; async fn method_a( @@ -462,7 +466,7 @@ pub mod foo { ); }; #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostBar { + pub trait Host: Send + HostBar + Sized { async fn bar_own_arg( &mut self, x: wasmtime::component::Resource, @@ -529,19 +533,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -956,7 +964,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum A {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostA { + pub trait HostA: Sized { async fn drop( &mut self, rep: wasmtime::component::Resource, @@ -971,22 +979,26 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostA {} + pub trait Host: Send + HostA + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1028,19 +1040,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1069,19 +1085,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1112,19 +1132,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1164,7 +1188,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum Foo {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostFoo { + pub trait HostFoo: Sized { async fn drop( &mut self, rep: wasmtime::component::Resource, @@ -1179,22 +1203,26 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostFoo {} + pub trait Host: Send + HostFoo + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/resources-import_concurrent.rs b/crates/component-macro/tests/expanded/resources-import_concurrent.rs new file mode 100644 index 000000000000..a7dc09b8072c --- /dev/null +++ b/crates/component-macro/tests/expanded/resources-import_concurrent.rs @@ -0,0 +1,2386 @@ +pub enum WorldResource {} +pub trait HostWorldResource: Sized { + type WorldResourceData; + fn new( + store: wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn static_foo( + store: wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()>; +} +impl<_T: HostWorldResource> HostWorldResource for &mut _T { + type WorldResourceData = _T::WorldResourceData; + fn new( + store: wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostWorldResource>::new(store) + } + fn foo( + store: wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostWorldResource>::foo(store, self_) + } + fn static_foo( + store: wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::WorldResourceData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostWorldResource>::static_foo(store) + } + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + HostWorldResource::drop(*self, rep) + } +} +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface1: exports::foo::foo::uses_resource_transitively::GuestIndices, + some_world_func2: wasmtime::component::ComponentExportIndex, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface1: exports::foo::foo::uses_resource_transitively::Guest, + some_world_func2: wasmtime::component::Func, +} +pub trait TheWorldImports: HostWorldResource { + type Data; + fn some_world_func( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; +} +pub trait TheWorldImportsGetHost< + T, + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: TheWorldImports; +} +impl TheWorldImportsGetHost for F +where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: TheWorldImports, +{ + type Host = O; +} +impl<_T: TheWorldImports> TheWorldImports for &mut _T { + type Data = _T::Data; + fn some_world_func( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as TheWorldImports>::some_world_func(store) + } +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface1 = exports::foo::foo::uses_resource_transitively::GuestIndices::new( + _component, + )?; + let some_world_func2 = _component + .export_index(None, "some-world-func2") + .ok_or_else(|| { + anyhow::anyhow!("no function export `some-world-func2` found") + })? + .1; + Ok(TheWorldIndices { + interface1, + some_world_func2, + }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface1 = exports::foo::foo::uses_resource_transitively::GuestIndices::new_instance( + &mut store, + _instance, + )?; + let some_world_func2 = _instance + .get_export(&mut store, None, "some-world-func2") + .ok_or_else(|| { + anyhow::anyhow!("no function export `some-world-func2` found") + })?; + Ok(TheWorldIndices { + interface1, + some_world_func2, + }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface1 = self.interface1.load(&mut store, &_instance)?; + let some_world_func2 = *_instance + .get_typed_func::< + (), + (wasmtime::component::Resource,), + >(&mut store, &self.some_world_func2)? + .func(); + Ok(TheWorld { + interface1, + some_world_func2, + }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost< + &'a mut T, + T, + Host: TheWorldImports, + >, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut linker = linker.root(); + linker + .resource( + "world-resource", + wasmtime::component::ResourceType::host::(), + move |mut store, rep| -> wasmtime::Result<()> { + HostWorldResource::drop( + &mut host_getter(store.data_mut()), + wasmtime::component::Resource::new_own(rep), + ) + }, + )?; + linker + .func_wrap_concurrent( + "[constructor]world-resource", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::new(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + linker + .func_wrap_concurrent( + "[method]world-resource.foo", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::Resource,)| + { + let host = caller; + let r = ::foo(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + linker + .func_wrap_concurrent( + "[static]world-resource.static-foo", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::static_foo(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + linker + .func_wrap_concurrent( + "some-world-func", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::some_world_func(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::resources::Host + + foo::foo::long_use_chain1::Host + foo::foo::long_use_chain2::Host + + foo::foo::long_use_chain3::Host + + foo::foo::long_use_chain4::Host + + foo::foo::transitive_interface_with_resource::Host + + TheWorldImports + 'static, + U: Send + foo::foo::resources::Host + + foo::foo::long_use_chain1::Host + foo::foo::long_use_chain2::Host + + foo::foo::long_use_chain3::Host + + foo::foo::long_use_chain4::Host + + foo::foo::transitive_interface_with_resource::Host + + TheWorldImports, + { + Self::add_to_linker_imports_get_host(linker, get)?; + foo::foo::resources::add_to_linker(linker, get)?; + foo::foo::long_use_chain1::add_to_linker(linker, get)?; + foo::foo::long_use_chain2::add_to_linker(linker, get)?; + foo::foo::long_use_chain3::add_to_linker(linker, get)?; + foo::foo::long_use_chain4::add_to_linker(linker, get)?; + foo::foo::transitive_interface_with_resource::add_to_linker(linker, get)?; + Ok(()) + } + pub async fn call_some_world_func2( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::Resource,), + >::new_unchecked(self.some_world_func2) + }; + let promise = callee.call_concurrent(store.as_context_mut(), ()).await?; + Ok(promise.map(|(v,)| v)) + } + pub fn foo_foo_uses_resource_transitively( + &self, + ) -> &exports::foo::foo::uses_resource_transitively::Guest { + &self.interface1 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod resources { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub enum Bar {} + pub trait HostBar: Sized { + type BarData; + fn new( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn static_a( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn method_a( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()>; + } + impl<_T: HostBar> HostBar for &mut _T { + type BarData = _T::BarData; + fn new( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostBar>::new(store) + } + fn static_a( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostBar>::static_a(store) + } + fn method_a( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostBar>::method_a(store, self_) + } + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + HostBar::drop(*self, rep) + } + } + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + pub struct NestedOwn { + #[component(name = "nested-bar")] + pub nested_bar: wasmtime::component::Resource, + } + impl core::fmt::Debug for NestedOwn { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("NestedOwn") + .field("nested-bar", &self.nested_bar) + .finish() + } + } + const _: () = { + assert!( + 4 == < NestedOwn as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < NestedOwn as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + pub struct NestedBorrow { + #[component(name = "nested-bar")] + pub nested_bar: wasmtime::component::Resource, + } + impl core::fmt::Debug for NestedBorrow { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("NestedBorrow") + .field("nested-bar", &self.nested_bar) + .finish() + } + } + const _: () = { + assert!( + 4 == < NestedBorrow as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < NestedBorrow as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub type SomeHandle = wasmtime::component::Resource; + const _: () = { + assert!( + 4 == < SomeHandle as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < SomeHandle as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub trait Host: HostBar + Sized { + type Data; + fn bar_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn bar_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn bar_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn tuple_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: (wasmtime::component::Resource, u32), + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn tuple_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: (wasmtime::component::Resource, u32), + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn tuple_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + wasmtime::component::Resource, + u32, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn option_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Option>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn option_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Option>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn option_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option< + wasmtime::component::Resource, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn result_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Result, ()>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn result_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Result, ()>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn result_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result< + wasmtime::component::Resource, + (), + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn list_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn record_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: NestedOwn, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn record_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: NestedBorrow, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn record_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> NestedOwn + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn func_with_handle_typedef( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: SomeHandle, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost< + &'a mut T, + T, + Host: Host + Send, + >, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/resources")?; + inst.resource( + "bar", + wasmtime::component::ResourceType::host::(), + move |mut store, rep| -> wasmtime::Result<()> { + HostBar::drop( + &mut host_getter(store.data_mut()), + wasmtime::component::Resource::new_own(rep), + ) + }, + )?; + inst.func_wrap_concurrent( + "[constructor]bar", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::new(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "[static]bar.static-a", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::static_a(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "[method]bar.method-a", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::Resource,)| + { + let host = caller; + let r = ::method_a(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "bar-own-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::Resource,)| + { + let host = caller; + let r = ::bar_own_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "bar-borrow-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::Resource,)| + { + let host = caller; + let r = ::bar_borrow_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "bar-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::bar_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "tuple-own-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): ((wasmtime::component::Resource, u32),)| + { + let host = caller; + let r = ::tuple_own_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "tuple-borrow-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): ((wasmtime::component::Resource, u32),)| + { + let host = caller; + let r = ::tuple_borrow_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "tuple-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::tuple_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ((wasmtime::component::Resource, u32),), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ((wasmtime::component::Resource, u32),), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "option-own-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Option>,)| + { + let host = caller; + let r = ::option_own_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "option-borrow-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Option>,)| + { + let host = caller; + let r = ::option_borrow_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "option-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::option_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Option>,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Option>,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "result-own-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Result, ()>,)| + { + let host = caller; + let r = ::result_own_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "result-borrow-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (Result, ()>,)| + { + let host = caller; + let r = ::result_borrow_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "result-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::result_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result, ()>,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result, ()>,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-own-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + ): ( + wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + )| + { + let host = caller; + let r = ::list_own_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-borrow-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + ): ( + wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + )| + { + let host = caller; + let r = ::list_borrow_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "list-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::list_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "record-own-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (NestedOwn,)| + { + let host = caller; + let r = ::record_own_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "record-borrow-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (NestedBorrow,)| + { + let host = caller; + let r = ::record_borrow_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "record-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::record_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(NestedOwn,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(NestedOwn,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "func-with-handle-typedef", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (SomeHandle,)| + { + let host = caller; + let r = ::func_with_handle_typedef(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn bar_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::bar_own_arg(store, x) + } + fn bar_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::bar_borrow_arg(store, x) + } + fn bar_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::bar_result(store) + } + fn tuple_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: (wasmtime::component::Resource, u32), + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::tuple_own_arg(store, x) + } + fn tuple_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: (wasmtime::component::Resource, u32), + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::tuple_borrow_arg(store, x) + } + fn tuple_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + wasmtime::component::Resource, + u32, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::tuple_result(store) + } + fn option_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Option>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::option_own_arg(store, x) + } + fn option_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Option>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::option_borrow_arg(store, x) + } + fn option_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option< + wasmtime::component::Resource, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::option_result(store) + } + fn result_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Result, ()>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::result_own_arg(store, x) + } + fn result_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: Result, ()>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::result_borrow_arg(store, x) + } + fn result_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result< + wasmtime::component::Resource, + (), + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::result_result(store) + } + fn list_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_own_arg(store, x) + } + fn list_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_borrow_arg(store, x) + } + fn list_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::Resource, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::list_result(store) + } + fn record_own_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: NestedOwn, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::record_own_arg(store, x) + } + fn record_borrow_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: NestedBorrow, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::record_borrow_arg(store, x) + } + fn record_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> NestedOwn + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::record_result(store) + } + fn func_with_handle_typedef( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: SomeHandle, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::func_with_handle_typedef(store, x) + } + } + } + #[allow(clippy::all)] + pub mod long_use_chain1 { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub enum A {} + pub trait HostA: Sized { + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()>; + } + impl<_T: HostA + ?Sized> HostA for &mut _T { + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + HostA::drop(*self, rep) + } + } + pub trait Host: HostA + Sized {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/long-use-chain1")?; + inst.resource( + "a", + wasmtime::component::ResourceType::host::(), + move |mut store, rep| -> wasmtime::Result<()> { + HostA::drop( + &mut host_getter(store.data_mut()), + wasmtime::component::Resource::new_own(rep), + ) + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + #[allow(clippy::all)] + pub mod long_use_chain2 { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type A = super::super::super::foo::foo::long_use_chain1::A; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/long-use-chain2")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + #[allow(clippy::all)] + pub mod long_use_chain3 { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type A = super::super::super::foo::foo::long_use_chain2::A; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/long-use-chain3")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + #[allow(clippy::all)] + pub mod long_use_chain4 { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type A = super::super::super::foo::foo::long_use_chain3::A; + pub trait Host { + type Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/long-use-chain4")?; + inst.func_wrap_concurrent( + "foo", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::foo(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::Resource,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::Resource + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::foo(store) + } + } + } + #[allow(clippy::all)] + pub mod transitive_interface_with_resource { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub enum Foo {} + pub trait HostFoo: Sized { + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()>; + } + impl<_T: HostFoo + ?Sized> HostFoo for &mut _T { + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + HostFoo::drop(*self, rep) + } + } + pub trait Host: HostFoo + Sized {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker + .instance("foo:foo/transitive-interface-with-resource")?; + inst.resource( + "foo", + wasmtime::component::ResourceType::host::(), + move |mut store, rep| -> wasmtime::Result<()> { + HostFoo::drop( + &mut host_getter(store.data_mut()), + wasmtime::component::Resource::new_own(rep), + ) + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod uses_resource_transitively { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Foo = super::super::super::super::foo::foo::transitive_interface_with_resource::Foo; + pub struct Guest { + handle: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + handle: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/uses-resource-transitively") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/uses-resource-transitively`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export( + &mut store, + None, + "foo:foo/uses-resource-transitively", + ) + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/uses-resource-transitively`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/uses-resource-transitively` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let handle = lookup("handle")?; + Ok(GuestIndices { handle }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let handle = *_instance + .get_typed_func::< + (wasmtime::component::Resource,), + (), + >(&mut store, &self.handle)? + .func(); + Ok(Guest { handle }) + } + } + impl Guest { + pub async fn call_handle( + &self, + mut store: S, + arg0: wasmtime::component::Resource, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::Resource,), + (), + >::new_unchecked(self.handle) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/resources-import_tracing_async.rs b/crates/component-macro/tests/expanded/resources-import_tracing_async.rs index 5332127243bc..013652af2943 100644 --- a/crates/component-macro/tests/expanded/resources-import_tracing_async.rs +++ b/crates/component-macro/tests/expanded/resources-import_tracing_async.rs @@ -1,6 +1,6 @@ pub enum WorldResource {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] -pub trait HostWorldResource { +pub trait HostWorldResource: Sized { async fn new(&mut self) -> wasmtime::component::Resource; async fn foo(&mut self, self_: wasmtime::component::Resource) -> (); async fn static_foo(&mut self) -> (); @@ -135,10 +135,11 @@ pub trait TheWorldImports: Send + HostWorldResource { } pub trait TheWorldImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: TheWorldImports; } -impl TheWorldImportsGetHost for F +impl TheWorldImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: TheWorldImports, @@ -250,9 +251,12 @@ const _: () = { let indices = TheWorldIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost<&'a mut T, T, Host: TheWorldImports>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> TheWorldImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -437,7 +441,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum Bar {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostBar { + pub trait HostBar: Sized { async fn new(&mut self) -> wasmtime::component::Resource; async fn static_a(&mut self) -> u32; async fn method_a( @@ -525,7 +529,7 @@ pub mod foo { ); }; #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostBar { + pub trait Host: Send + HostBar + Sized { async fn bar_own_arg( &mut self, x: wasmtime::component::Resource, @@ -592,19 +596,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1347,7 +1355,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum A {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostA { + pub trait HostA: Sized { async fn drop( &mut self, rep: wasmtime::component::Resource, @@ -1362,22 +1370,26 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostA {} + pub trait Host: Send + HostA + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1419,19 +1431,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1460,19 +1476,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1503,19 +1523,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -1568,7 +1592,7 @@ pub mod foo { use wasmtime::component::__internal::{anyhow, Box}; pub enum Foo {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostFoo { + pub trait HostFoo: Sized { async fn drop( &mut self, rep: wasmtime::component::Resource, @@ -1583,22 +1607,26 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostFoo {} + pub trait Host: Send + HostFoo + Sized {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/share-types.rs b/crates/component-macro/tests/expanded/share-types.rs index 7d3d2b33c093..c7f3f8be1800 100644 --- a/crates/component-macro/tests/expanded/share-types.rs +++ b/crates/component-macro/tests/expanded/share-types.rs @@ -228,19 +228,23 @@ pub mod foo { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/http-types")?; Ok(()) @@ -277,19 +281,20 @@ pub mod http_fetch { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host GetHost<&'a mut T, T, Host: Host>>( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("http-fetch")?; inst.func_wrap( @@ -413,7 +418,10 @@ pub mod exports { &self, mut store: S, arg0: &Request, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&Request,), diff --git a/crates/component-macro/tests/expanded/share-types_async.rs b/crates/component-macro/tests/expanded/share-types_async.rs index b6f3d4e9b6b5..cdc9db0b434a 100644 --- a/crates/component-macro/tests/expanded/share-types_async.rs +++ b/crates/component-macro/tests/expanded/share-types_async.rs @@ -236,19 +236,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -290,19 +294,23 @@ pub mod http_fetch { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/share-types_concurrent.rs b/crates/component-macro/tests/expanded/share-types_concurrent.rs new file mode 100644 index 000000000000..0d79f4f067ee --- /dev/null +++ b/crates/component-macro/tests/expanded/share-types_concurrent.rs @@ -0,0 +1,499 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `http-interface`. +/// +/// This structure is created through [`HttpInterfacePre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`HttpInterface`] as well. +pub struct HttpInterfacePre { + instance_pre: wasmtime::component::InstancePre, + indices: HttpInterfaceIndices, +} +impl Clone for HttpInterfacePre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> HttpInterfacePre<_T> { + /// Creates a new copy of `HttpInterfacePre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = HttpInterfaceIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`HttpInterface`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `http-interface`. +/// +/// This is an implementation detail of [`HttpInterfacePre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`HttpInterface`] as well. +#[derive(Clone)] +pub struct HttpInterfaceIndices { + interface0: exports::http_handler::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `http-interface`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`HttpInterface::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`HttpInterfacePre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`HttpInterfacePre::instantiate_async`] to +/// create a [`HttpInterface`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`HttpInterface::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`HttpInterfaceIndices::new_instance`] followed +/// by [`HttpInterfaceIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct HttpInterface { + interface0: exports::http_handler::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl HttpInterfaceIndices { + /// Creates a new copy of `HttpInterfaceIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::http_handler::GuestIndices::new(_component)?; + Ok(HttpInterfaceIndices { interface0 }) + } + /// Creates a new instance of [`HttpInterfaceIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`HttpInterface`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`HttpInterface`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::http_handler::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(HttpInterfaceIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`HttpInterface`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(HttpInterface { interface0 }) + } + } + impl HttpInterface { + /// Convenience wrapper around [`HttpInterfacePre::new`] and + /// [`HttpInterfacePre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + HttpInterfacePre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`HttpInterfaceIndices::new_instance`] and + /// [`HttpInterfaceIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = HttpInterfaceIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::http_types::Host + http_fetch::Host + 'static, + U: Send + foo::foo::http_types::Host + http_fetch::Host, + { + foo::foo::http_types::add_to_linker(linker, get)?; + http_fetch::add_to_linker(linker, get)?; + Ok(()) + } + pub fn http_handler(&self) -> &exports::http_handler::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod http_types { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct Request { + #[component(name = "method")] + pub method: wasmtime::component::__internal::String, + } + impl core::fmt::Debug for Request { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Request").field("method", &self.method).finish() + } + } + const _: () = { + assert!(8 == < Request as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Request as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct Response { + #[component(name = "body")] + pub body: wasmtime::component::__internal::String, + } + impl core::fmt::Debug for Response { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Response").field("body", &self.body).finish() + } + } + const _: () = { + assert!(8 == < Response as wasmtime::component::ComponentType >::SIZE32); + assert!( + 4 == < Response as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/http-types")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} +#[allow(clippy::all)] +pub mod http_fetch { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Request = super::foo::foo::http_types::Request; + const _: () = { + assert!(8 == < Request as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Request as wasmtime::component::ComponentType >::ALIGN32); + }; + pub type Response = super::foo::foo::http_types::Response; + const _: () = { + assert!(8 == < Response as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Response as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn fetch_request( + store: wasmtime::StoreContextMut<'_, Self::Data>, + request: Request, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Response + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("http-fetch")?; + inst.func_wrap_concurrent( + "fetch-request", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Request,)| { + let host = caller; + let r = ::fetch_request(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Response,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Response,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn fetch_request( + store: wasmtime::StoreContextMut<'_, Self::Data>, + request: Request, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Response + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::fetch_request(store, request) + } + } +} +pub mod exports { + #[allow(clippy::all)] + pub mod http_handler { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Request = super::super::foo::foo::http_types::Request; + const _: () = { + assert!(8 == < Request as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Request as wasmtime::component::ComponentType >::ALIGN32); + }; + pub type Response = super::super::foo::foo::http_types::Response; + const _: () = { + assert!(8 == < Response as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Response as wasmtime::component::ComponentType >::ALIGN32); + }; + pub struct Guest { + handle_request: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + handle_request: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "http-handler") + .ok_or_else(|| { + anyhow::anyhow!("no exported instance named `http-handler`") + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "http-handler") + .ok_or_else(|| { + anyhow::anyhow!("no exported instance named `http-handler`") + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `http-handler` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let handle_request = lookup("handle-request")?; + Ok(GuestIndices { handle_request }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let handle_request = *_instance + .get_typed_func::< + (&Request,), + (Response,), + >(&mut store, &self.handle_request)? + .func(); + Ok(Guest { handle_request }) + } + } + impl Guest { + pub async fn call_handle_request( + &self, + mut store: S, + arg0: Request, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Request,), + (Response,), + >::new_unchecked(self.handle_request) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } +} diff --git a/crates/component-macro/tests/expanded/share-types_tracing_async.rs b/crates/component-macro/tests/expanded/share-types_tracing_async.rs index be08b82994fa..c7d25823c530 100644 --- a/crates/component-macro/tests/expanded/share-types_tracing_async.rs +++ b/crates/component-macro/tests/expanded/share-types_tracing_async.rs @@ -236,19 +236,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -290,19 +294,23 @@ pub mod http_fetch { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/simple-functions.rs b/crates/component-macro/tests/expanded/simple-functions.rs index 9b4a809d9713..0b9f6316f745 100644 --- a/crates/component-macro/tests/expanded/simple-functions.rs +++ b/crates/component-macro/tests/expanded/simple-functions.rs @@ -196,19 +196,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/simple")?; inst.func_wrap( @@ -427,7 +431,10 @@ pub mod exports { pub fn call_f1( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -442,7 +449,10 @@ pub mod exports { &self, mut store: S, arg0: u32, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u32,), @@ -458,7 +468,10 @@ pub mod exports { mut store: S, arg0: u32, arg1: u32, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u32, u32), @@ -472,7 +485,10 @@ pub mod exports { pub fn call_f4( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -486,7 +502,10 @@ pub mod exports { pub fn call_f5( &self, mut store: S, - ) -> wasmtime::Result<(u32, u32)> { + ) -> wasmtime::Result<(u32, u32)> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -503,7 +522,10 @@ pub mod exports { arg0: u32, arg1: u32, arg2: u32, - ) -> wasmtime::Result<(u32, u32, u32)> { + ) -> wasmtime::Result<(u32, u32, u32)> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (u32, u32, u32), diff --git a/crates/component-macro/tests/expanded/simple-functions_async.rs b/crates/component-macro/tests/expanded/simple-functions_async.rs index 8f564e80ae1d..b90c30015051 100644 --- a/crates/component-macro/tests/expanded/simple-functions_async.rs +++ b/crates/component-macro/tests/expanded/simple-functions_async.rs @@ -204,19 +204,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/simple-functions_concurrent.rs b/crates/component-macro/tests/expanded/simple-functions_concurrent.rs new file mode 100644 index 000000000000..830a5de01aad --- /dev/null +++ b/crates/component-macro/tests/expanded/simple-functions_concurrent.rs @@ -0,0 +1,808 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::simple::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::simple::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::simple::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::simple::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::simple::Host + 'static, + U: Send + foo::foo::simple::Host, + { + foo::foo::simple::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_simple(&self) -> &exports::foo::foo::simple::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod simple { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn f1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: u32, + b: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f5( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (u32, u32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn f6( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: u32, + b: u32, + c: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (u32, u32, u32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/simple")?; + inst.func_wrap_concurrent( + "f1", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::f1(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f2", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u32,)| { + let host = caller; + let r = ::f2(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f3", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0, arg1): (u32, u32)| + { + let host = caller; + let r = ::f3(host, arg0, arg1); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f4", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::f4(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(u32,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f5", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::f5(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((u32, u32),)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((u32, u32),)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "f6", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0, arg1, arg2): (u32, u32, u32)| + { + let host = caller; + let r = ::f6(host, arg0, arg1, arg2); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((u32, u32, u32),)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<((u32, u32, u32),)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn f1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f1(store) + } + fn f2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f2(store, a) + } + fn f3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: u32, + b: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f3(store, a, b) + } + fn f4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> u32 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f4(store) + } + fn f5( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (u32, u32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f5(store) + } + fn f6( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: u32, + b: u32, + c: u32, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> (u32, u32, u32) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::f6(store, a, b, c) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod simple { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + f1: wasmtime::component::Func, + f2: wasmtime::component::Func, + f3: wasmtime::component::Func, + f4: wasmtime::component::Func, + f5: wasmtime::component::Func, + f6: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + f1: wasmtime::component::ComponentExportIndex, + f2: wasmtime::component::ComponentExportIndex, + f3: wasmtime::component::ComponentExportIndex, + f4: wasmtime::component::ComponentExportIndex, + f5: wasmtime::component::ComponentExportIndex, + f6: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/simple") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/simple`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/simple") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/simple`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/simple` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let f1 = lookup("f1")?; + let f2 = lookup("f2")?; + let f3 = lookup("f3")?; + let f4 = lookup("f4")?; + let f5 = lookup("f5")?; + let f6 = lookup("f6")?; + Ok(GuestIndices { + f1, + f2, + f3, + f4, + f5, + f6, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let f1 = *_instance + .get_typed_func::<(), ()>(&mut store, &self.f1)? + .func(); + let f2 = *_instance + .get_typed_func::<(u32,), ()>(&mut store, &self.f2)? + .func(); + let f3 = *_instance + .get_typed_func::<(u32, u32), ()>(&mut store, &self.f3)? + .func(); + let f4 = *_instance + .get_typed_func::<(), (u32,)>(&mut store, &self.f4)? + .func(); + let f5 = *_instance + .get_typed_func::<(), ((u32, u32),)>(&mut store, &self.f5)? + .func(); + let f6 = *_instance + .get_typed_func::< + (u32, u32, u32), + ((u32, u32, u32),), + >(&mut store, &self.f6)? + .func(); + Ok(Guest { f1, f2, f3, f4, f5, f6 }) + } + } + impl Guest { + pub async fn call_f1( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (), + >::new_unchecked(self.f1) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise) + } + pub async fn call_f2( + &self, + mut store: S, + arg0: u32, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u32,), + (), + >::new_unchecked(self.f2) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_f3( + &self, + mut store: S, + arg0: u32, + arg1: u32, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u32, u32), + (), + >::new_unchecked(self.f3) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0, arg1)) + .await?; + Ok(promise) + } + pub async fn call_f4( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (u32,), + >::new_unchecked(self.f4) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_f5( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + ((u32, u32),), + >::new_unchecked(self.f5) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_f6( + &self, + mut store: S, + arg0: u32, + arg1: u32, + arg2: u32, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (u32, u32, u32), + ((u32, u32, u32),), + >::new_unchecked(self.f6) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0, arg1, arg2)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/simple-functions_tracing_async.rs b/crates/component-macro/tests/expanded/simple-functions_tracing_async.rs index d9771b87beae..d431f6ba6b53 100644 --- a/crates/component-macro/tests/expanded/simple-functions_tracing_async.rs +++ b/crates/component-macro/tests/expanded/simple-functions_tracing_async.rs @@ -204,19 +204,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/simple-lists.rs b/crates/component-macro/tests/expanded/simple-lists.rs index ddd44d6cca17..9b3c75624ddf 100644 --- a/crates/component-macro/tests/expanded/simple-lists.rs +++ b/crates/component-macro/tests/expanded/simple-lists.rs @@ -213,19 +213,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/simple-lists")?; inst.func_wrap( @@ -464,7 +468,10 @@ pub mod exports { &self, mut store: S, arg0: &[u32], - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[u32],), @@ -478,7 +485,10 @@ pub mod exports { pub fn call_simple_list2( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -499,7 +509,10 @@ pub mod exports { wasmtime::component::__internal::Vec, wasmtime::component::__internal::Vec, ), - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[u32], &[u32]), @@ -523,7 +536,10 @@ pub mod exports { wasmtime::component::__internal::Vec< wasmtime::component::__internal::Vec, >, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&[wasmtime::component::__internal::Vec],), diff --git a/crates/component-macro/tests/expanded/simple-lists_async.rs b/crates/component-macro/tests/expanded/simple-lists_async.rs index d1ddd48e69dd..530e240d9a2e 100644 --- a/crates/component-macro/tests/expanded/simple-lists_async.rs +++ b/crates/component-macro/tests/expanded/simple-lists_async.rs @@ -223,19 +223,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/simple-lists_concurrent.rs b/crates/component-macro/tests/expanded/simple-lists_concurrent.rs new file mode 100644 index 000000000000..1dba45c7ca49 --- /dev/null +++ b/crates/component-macro/tests/expanded/simple-lists_concurrent.rs @@ -0,0 +1,773 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `my-world`. +/// +/// This structure is created through [`MyWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`MyWorld`] as well. +pub struct MyWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: MyWorldIndices, +} +impl Clone for MyWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> MyWorldPre<_T> { + /// Creates a new copy of `MyWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = MyWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`MyWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `my-world`. +/// +/// This is an implementation detail of [`MyWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`MyWorld`] as well. +#[derive(Clone)] +pub struct MyWorldIndices { + interface0: exports::foo::foo::simple_lists::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `my-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`MyWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`MyWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`MyWorldPre::instantiate_async`] to +/// create a [`MyWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`MyWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`MyWorldIndices::new_instance`] followed +/// by [`MyWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct MyWorld { + interface0: exports::foo::foo::simple_lists::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl MyWorldIndices { + /// Creates a new copy of `MyWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::simple_lists::GuestIndices::new( + _component, + )?; + Ok(MyWorldIndices { interface0 }) + } + /// Creates a new instance of [`MyWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`MyWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`MyWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::simple_lists::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(MyWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`MyWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(MyWorld { interface0 }) + } + } + impl MyWorld { + /// Convenience wrapper around [`MyWorldPre::new`] and + /// [`MyWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + MyWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`MyWorldIndices::new_instance`] and + /// [`MyWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = MyWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::simple_lists::Host + 'static, + U: Send + foo::foo::simple_lists::Host, + { + foo::foo::simple_lists::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_simple_lists(&self) -> &exports::foo::foo::simple_lists::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod simple_lists { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn simple_list1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + l: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn simple_list2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn simple_list3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: wasmtime::component::__internal::Vec, + b: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn simple_list4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + l: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/simple-lists")?; + inst.func_wrap_concurrent( + "simple-list1", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::Vec,)| + { + let host = caller; + let r = ::simple_list1(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "simple-list2", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::simple_list2(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::Vec,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "simple-list3", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + arg1, + ): ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + )| + { + let host = caller; + let r = ::simple_list3(host, arg0, arg1); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ), + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ), + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "simple-list4", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + ): ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + )| + { + let host = caller; + let r = ::simple_list4(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn simple_list1( + store: wasmtime::StoreContextMut<'_, Self::Data>, + l: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::simple_list1(store, l) + } + fn simple_list2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + u32, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::simple_list2(store) + } + fn simple_list3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: wasmtime::component::__internal::Vec, + b: wasmtime::component::__internal::Vec, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::simple_list3(store, a, b) + } + fn simple_list4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + l: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::simple_list4(store, l) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod simple_lists { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + simple_list1: wasmtime::component::Func, + simple_list2: wasmtime::component::Func, + simple_list3: wasmtime::component::Func, + simple_list4: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + simple_list1: wasmtime::component::ComponentExportIndex, + simple_list2: wasmtime::component::ComponentExportIndex, + simple_list3: wasmtime::component::ComponentExportIndex, + simple_list4: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/simple-lists") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/simple-lists`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/simple-lists") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/simple-lists`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/simple-lists` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let simple_list1 = lookup("simple-list1")?; + let simple_list2 = lookup("simple-list2")?; + let simple_list3 = lookup("simple-list3")?; + let simple_list4 = lookup("simple-list4")?; + Ok(GuestIndices { + simple_list1, + simple_list2, + simple_list3, + simple_list4, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let simple_list1 = *_instance + .get_typed_func::< + (&[u32],), + (), + >(&mut store, &self.simple_list1)? + .func(); + let simple_list2 = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::Vec,), + >(&mut store, &self.simple_list2)? + .func(); + let simple_list3 = *_instance + .get_typed_func::< + (&[u32], &[u32]), + ( + ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ), + ), + >(&mut store, &self.simple_list3)? + .func(); + let simple_list4 = *_instance + .get_typed_func::< + (&[wasmtime::component::__internal::Vec],), + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ), + >(&mut store, &self.simple_list4)? + .func(); + Ok(Guest { + simple_list1, + simple_list2, + simple_list3, + simple_list4, + }) + } + } + impl Guest { + pub async fn call_simple_list1( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::Vec,), + (), + >::new_unchecked(self.simple_list1) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_simple_list2( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::Vec,), + >::new_unchecked(self.simple_list2) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_simple_list3( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec, + arg1: wasmtime::component::__internal::Vec, + ) -> wasmtime::Result< + wasmtime::component::Promise< + ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ), + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ), + ( + ( + wasmtime::component::__internal::Vec, + wasmtime::component::__internal::Vec, + ), + ), + >::new_unchecked(self.simple_list3) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0, arg1)) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_simple_list4( + &self, + mut store: S, + arg0: wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ), + ( + wasmtime::component::__internal::Vec< + wasmtime::component::__internal::Vec, + >, + ), + >::new_unchecked(self.simple_list4) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/simple-lists_tracing_async.rs b/crates/component-macro/tests/expanded/simple-lists_tracing_async.rs index 5170ff1563d6..50c00bdd8c2e 100644 --- a/crates/component-macro/tests/expanded/simple-lists_tracing_async.rs +++ b/crates/component-macro/tests/expanded/simple-lists_tracing_async.rs @@ -223,19 +223,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/simple-wasi.rs b/crates/component-macro/tests/expanded/simple-wasi.rs index 2feddc5520e8..09545b1ff29d 100644 --- a/crates/component-macro/tests/expanded/simple-wasi.rs +++ b/crates/component-macro/tests/expanded/simple-wasi.rs @@ -241,19 +241,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/wasi-filesystem")?; inst.func_wrap( @@ -299,19 +303,23 @@ pub mod foo { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/wall-clock")?; Ok(()) diff --git a/crates/component-macro/tests/expanded/simple-wasi_async.rs b/crates/component-macro/tests/expanded/simple-wasi_async.rs index 5b95ff182556..9f4cc0ff0c3c 100644 --- a/crates/component-macro/tests/expanded/simple-wasi_async.rs +++ b/crates/component-macro/tests/expanded/simple-wasi_async.rs @@ -249,19 +249,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -316,19 +320,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs b/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs new file mode 100644 index 000000000000..1c90bcf8cf4f --- /dev/null +++ b/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs @@ -0,0 +1,440 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `wasi`. +/// +/// This structure is created through [`WasiPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Wasi`] as well. +pub struct WasiPre { + instance_pre: wasmtime::component::InstancePre, + indices: WasiIndices, +} +impl Clone for WasiPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> WasiPre<_T> { + /// Creates a new copy of `WasiPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = WasiIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Wasi`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `wasi`. +/// +/// This is an implementation detail of [`WasiPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Wasi`] as well. +#[derive(Clone)] +pub struct WasiIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `wasi`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Wasi::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`WasiPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`WasiPre::instantiate_async`] to +/// create a [`Wasi`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Wasi::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`WasiIndices::new_instance`] followed +/// by [`WasiIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Wasi {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl WasiIndices { + /// Creates a new copy of `WasiIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(WasiIndices {}) + } + /// Creates a new instance of [`WasiIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Wasi`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Wasi`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(WasiIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Wasi`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Wasi {}) + } + } + impl Wasi { + /// Convenience wrapper around [`WasiPre::new`] and + /// [`WasiPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + WasiPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`WasiIndices::new_instance`] and + /// [`WasiIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = WasiIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::wasi_filesystem::Host + + foo::foo::wall_clock::Host + 'static, + U: Send + foo::foo::wasi_filesystem::Host + + foo::foo::wall_clock::Host, + { + foo::foo::wasi_filesystem::add_to_linker(linker, get)?; + foo::foo::wall_clock::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod wasi_filesystem { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct DescriptorStat {} + impl core::fmt::Debug for DescriptorStat { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("DescriptorStat").finish() + } + } + const _: () = { + assert!( + 0 == < DescriptorStat as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < DescriptorStat as wasmtime::component::ComponentType + >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(enum)] + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u8)] + pub enum Errno { + #[component(name = "e")] + E, + } + impl Errno { + pub fn name(&self) -> &'static str { + match self { + Errno::E => "e", + } + } + pub fn message(&self) -> &'static str { + match self { + Errno::E => "", + } + } + } + impl core::fmt::Debug for Errno { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Errno") + .field("code", &(*self as i32)) + .field("name", &self.name()) + .field("message", &self.message()) + .finish() + } + } + impl core::fmt::Display for Errno { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{} (error {})", self.name(), * self as i32) + } + } + impl std::error::Error for Errno {} + const _: () = { + assert!(1 == < Errno as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Errno as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn create_directory_at( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(), Errno> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn stat( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/wasi-filesystem")?; + inst.func_wrap_concurrent( + "create-directory-at", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::create_directory_at(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result<(), Errno>,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result<(), Errno>,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "stat", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::stat(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn create_directory_at( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(), Errno> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::create_directory_at(store) + } + fn stat( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::stat(store) + } + } + } + #[allow(clippy::all)] + pub mod wall_clock { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/wall-clock")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} diff --git a/crates/component-macro/tests/expanded/simple-wasi_tracing_async.rs b/crates/component-macro/tests/expanded/simple-wasi_tracing_async.rs index 17b68e5c2c0e..91a225622285 100644 --- a/crates/component-macro/tests/expanded/simple-wasi_tracing_async.rs +++ b/crates/component-macro/tests/expanded/simple-wasi_tracing_async.rs @@ -249,19 +249,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -342,19 +346,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/small-anonymous.rs b/crates/component-macro/tests/expanded/small-anonymous.rs index f14766767851..484e60a71bba 100644 --- a/crates/component-macro/tests/expanded/small-anonymous.rs +++ b/crates/component-macro/tests/expanded/small-anonymous.rs @@ -238,19 +238,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/anon")?; inst.func_wrap( @@ -431,7 +435,10 @@ pub mod exports { mut store: S, ) -> wasmtime::Result< Result, Error>, - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/small-anonymous_async.rs b/crates/component-macro/tests/expanded/small-anonymous_async.rs index 239bca6be1e2..bc0e30cfd6db 100644 --- a/crates/component-macro/tests/expanded/small-anonymous_async.rs +++ b/crates/component-macro/tests/expanded/small-anonymous_async.rs @@ -246,19 +246,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs b/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs new file mode 100644 index 000000000000..bca9c635cc56 --- /dev/null +++ b/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs @@ -0,0 +1,535 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::anon::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::anon::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::anon::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::anon::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::anon::Host + 'static, + U: Send + foo::foo::anon::Host, + { + foo::foo::anon::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_anon(&self) -> &exports::foo::foo::anon::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod anon { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(enum)] + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u8)] + pub enum Error { + #[component(name = "success")] + Success, + #[component(name = "failure")] + Failure, + } + impl Error { + pub fn name(&self) -> &'static str { + match self { + Error::Success => "success", + Error::Failure => "failure", + } + } + pub fn message(&self) -> &'static str { + match self { + Error::Success => "", + Error::Failure => "", + } + } + } + impl core::fmt::Debug for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Error") + .field("code", &(*self as i32)) + .field("name", &self.name()) + .field("message", &self.message()) + .finish() + } + } + impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{} (error {})", self.name(), * self as i32) + } + } + impl std::error::Error for Error {} + const _: () = { + assert!(1 == < Error as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Error as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn option_test( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result< + Option, + Error, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/anon")?; + inst.func_wrap_concurrent( + "option-test", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::option_test(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + Result< + Option, + Error, + >, + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + Result< + Option, + Error, + >, + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn option_test( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result< + Option, + Error, + > + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::option_test(store) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod anon { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(enum)] + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u8)] + pub enum Error { + #[component(name = "success")] + Success, + #[component(name = "failure")] + Failure, + } + impl Error { + pub fn name(&self) -> &'static str { + match self { + Error::Success => "success", + Error::Failure => "failure", + } + } + pub fn message(&self) -> &'static str { + match self { + Error::Success => "", + Error::Failure => "", + } + } + } + impl core::fmt::Debug for Error { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("Error") + .field("code", &(*self as i32)) + .field("name", &self.name()) + .field("message", &self.message()) + .finish() + } + } + impl core::fmt::Display for Error { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + write!(f, "{} (error {})", self.name(), * self as i32) + } + } + impl std::error::Error for Error {} + const _: () = { + assert!( + 1 == < Error as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < Error as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub struct Guest { + option_test: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + option_test: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/anon") + .ok_or_else(|| { + anyhow::anyhow!("no exported instance named `foo:foo/anon`") + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/anon") + .ok_or_else(|| { + anyhow::anyhow!("no exported instance named `foo:foo/anon`") + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/anon` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let option_test = lookup("option-test")?; + Ok(GuestIndices { option_test }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let option_test = *_instance + .get_typed_func::< + (), + ( + Result< + Option, + Error, + >, + ), + >(&mut store, &self.option_test)? + .func(); + Ok(Guest { option_test }) + } + } + impl Guest { + pub async fn call_option_test( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + Result< + Option, + Error, + >, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + ( + Result< + Option, + Error, + >, + ), + >::new_unchecked(self.option_test) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/small-anonymous_tracing_async.rs b/crates/component-macro/tests/expanded/small-anonymous_tracing_async.rs index 1226081d5fad..0b5e21f4fab6 100644 --- a/crates/component-macro/tests/expanded/small-anonymous_tracing_async.rs +++ b/crates/component-macro/tests/expanded/small-anonymous_tracing_async.rs @@ -246,19 +246,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/smoke-default.rs b/crates/component-macro/tests/expanded/smoke-default.rs index e9ab3af1d8d4..4b5aae7ff978 100644 --- a/crates/component-macro/tests/expanded/smoke-default.rs +++ b/crates/component-macro/tests/expanded/smoke-default.rs @@ -170,7 +170,10 @@ const _: () = { pub fn call_y( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::<(), ()>::new_unchecked(self.y) }; diff --git a/crates/component-macro/tests/expanded/smoke-default_concurrent.rs b/crates/component-macro/tests/expanded/smoke-default_concurrent.rs new file mode 100644 index 000000000000..3295b1a392f6 --- /dev/null +++ b/crates/component-macro/tests/expanded/smoke-default_concurrent.rs @@ -0,0 +1,190 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + y: wasmtime::component::ComponentExportIndex, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + y: wasmtime::component::Func, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let y = _component + .export_index(None, "y") + .ok_or_else(|| anyhow::anyhow!("no function export `y` found"))? + .1; + Ok(TheWorldIndices { y }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let y = _instance + .get_export(&mut store, None, "y") + .ok_or_else(|| anyhow::anyhow!("no function export `y` found"))?; + Ok(TheWorldIndices { y }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let y = *_instance.get_typed_func::<(), ()>(&mut store, &self.y)?.func(); + Ok(TheWorld { y }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub async fn call_y( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::<(), ()>::new_unchecked(self.y) + }; + let promise = callee.call_concurrent(store.as_context_mut(), ()).await?; + Ok(promise) + } + } +}; diff --git a/crates/component-macro/tests/expanded/smoke-export.rs b/crates/component-macro/tests/expanded/smoke-export.rs index 498170dd624f..401d3da0f1a2 100644 --- a/crates/component-macro/tests/expanded/smoke-export.rs +++ b/crates/component-macro/tests/expanded/smoke-export.rs @@ -250,7 +250,10 @@ pub mod exports { pub fn call_y( &self, mut store: S, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::<(), ()>::new_unchecked(self.y) }; diff --git a/crates/component-macro/tests/expanded/smoke-export_concurrent.rs b/crates/component-macro/tests/expanded/smoke-export_concurrent.rs new file mode 100644 index 000000000000..d64ba694ee66 --- /dev/null +++ b/crates/component-macro/tests/expanded/smoke-export_concurrent.rs @@ -0,0 +1,271 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::the_name::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::the_name::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::the_name::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::the_name::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn the_name(&self) -> &exports::the_name::Guest { + &self.interface0 + } + } +}; +pub mod exports { + #[allow(clippy::all)] + pub mod the_name { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + y: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + y: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "the-name") + .ok_or_else(|| { + anyhow::anyhow!("no exported instance named `the-name`") + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "the-name") + .ok_or_else(|| { + anyhow::anyhow!("no exported instance named `the-name`") + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `the-name` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let y = lookup("y")?; + Ok(GuestIndices { y }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let y = *_instance.get_typed_func::<(), ()>(&mut store, &self.y)?.func(); + Ok(Guest { y }) + } + } + impl Guest { + pub async fn call_y( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::<(), ()>::new_unchecked(self.y) + }; + let promise = callee.call_concurrent(store.as_context_mut(), ()).await?; + Ok(promise) + } + } + } +} diff --git a/crates/component-macro/tests/expanded/smoke.rs b/crates/component-macro/tests/expanded/smoke.rs index 97e1b0fe51b6..b22a0aa67a3e 100644 --- a/crates/component-macro/tests/expanded/smoke.rs +++ b/crates/component-macro/tests/expanded/smoke.rs @@ -176,19 +176,20 @@ pub mod imports { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host GetHost<&'a mut T, T, Host: Host>>( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("imports")?; inst.func_wrap( diff --git a/crates/component-macro/tests/expanded/smoke_async.rs b/crates/component-macro/tests/expanded/smoke_async.rs index 441d2f7eb40a..8881ec5defc1 100644 --- a/crates/component-macro/tests/expanded/smoke_async.rs +++ b/crates/component-macro/tests/expanded/smoke_async.rs @@ -184,19 +184,23 @@ pub mod imports { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/smoke_concurrent.rs b/crates/component-macro/tests/expanded/smoke_concurrent.rs new file mode 100644 index 000000000000..fffac707714e --- /dev/null +++ b/crates/component-macro/tests/expanded/smoke_concurrent.rs @@ -0,0 +1,274 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(TheWorldIndices {}) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(TheWorldIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(TheWorld {}) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + imports::Host + 'static, + U: Send + imports::Host, + { + imports::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +#[allow(clippy::all)] +pub mod imports { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn y( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("imports")?; + inst.func_wrap_concurrent( + "y", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::y(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn y( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::y(store) + } + } +} diff --git a/crates/component-macro/tests/expanded/smoke_tracing_async.rs b/crates/component-macro/tests/expanded/smoke_tracing_async.rs index 02b979f4a7bb..319acdcf7339 100644 --- a/crates/component-macro/tests/expanded/smoke_tracing_async.rs +++ b/crates/component-macro/tests/expanded/smoke_tracing_async.rs @@ -184,19 +184,23 @@ pub mod imports { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/strings.rs b/crates/component-macro/tests/expanded/strings.rs index 40b22082c941..a9cd8a152f14 100644 --- a/crates/component-macro/tests/expanded/strings.rs +++ b/crates/component-macro/tests/expanded/strings.rs @@ -197,19 +197,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/strings")?; inst.func_wrap( @@ -384,7 +388,10 @@ pub mod exports { &self, mut store: S, arg0: &str, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&str,), @@ -398,7 +405,10 @@ pub mod exports { pub fn call_b( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -414,7 +424,10 @@ pub mod exports { mut store: S, arg0: &str, arg1: &str, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&str, &str), diff --git a/crates/component-macro/tests/expanded/strings_async.rs b/crates/component-macro/tests/expanded/strings_async.rs index 4d448ab0a345..52c27d1c15c1 100644 --- a/crates/component-macro/tests/expanded/strings_async.rs +++ b/crates/component-macro/tests/expanded/strings_async.rs @@ -205,19 +205,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/strings_concurrent.rs b/crates/component-macro/tests/expanded/strings_concurrent.rs new file mode 100644 index 000000000000..52de04401734 --- /dev/null +++ b/crates/component-macro/tests/expanded/strings_concurrent.rs @@ -0,0 +1,595 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices { + interface0: exports::foo::foo::strings::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld { + interface0: exports::foo::foo::strings::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::strings::GuestIndices::new(_component)?; + Ok(TheWorldIndices { interface0 }) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::strings::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(TheWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(TheWorld { interface0 }) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::strings::Host + 'static, + U: Send + foo::foo::strings::Host, + { + foo::foo::strings::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_strings(&self) -> &exports::foo::foo::strings::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod strings { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub trait Host { + type Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::String, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn b( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::String + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn c( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: wasmtime::component::__internal::String, + b: wasmtime::component::__internal::String, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::String + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/strings")?; + inst.func_wrap_concurrent( + "a", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::__internal::String,)| + { + let host = caller; + let r = ::a(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "b", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::b(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::String,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::String,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "c", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + arg1, + ): ( + wasmtime::component::__internal::String, + wasmtime::component::__internal::String, + )| + { + let host = caller; + let r = ::c(host, arg0, arg1); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::String,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (wasmtime::component::__internal::String,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: wasmtime::component::__internal::String, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a(store, x) + } + fn b( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::String + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::b(store) + } + fn c( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: wasmtime::component::__internal::String, + b: wasmtime::component::__internal::String, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> wasmtime::component::__internal::String + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::c(store, a, b) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod strings { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub struct Guest { + a: wasmtime::component::Func, + b: wasmtime::component::Func, + c: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + a: wasmtime::component::ComponentExportIndex, + b: wasmtime::component::ComponentExportIndex, + c: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/strings") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/strings`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/strings") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/strings`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/strings` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let a = lookup("a")?; + let b = lookup("b")?; + let c = lookup("c")?; + Ok(GuestIndices { a, b, c }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let a = *_instance + .get_typed_func::<(&str,), ()>(&mut store, &self.a)? + .func(); + let b = *_instance + .get_typed_func::< + (), + (wasmtime::component::__internal::String,), + >(&mut store, &self.b)? + .func(); + let c = *_instance + .get_typed_func::< + (&str, &str), + (wasmtime::component::__internal::String,), + >(&mut store, &self.c)? + .func(); + Ok(Guest { a, b, c }) + } + } + impl Guest { + pub async fn call_a( + &self, + mut store: S, + arg0: wasmtime::component::__internal::String, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (wasmtime::component::__internal::String,), + (), + >::new_unchecked(self.a) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_b( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::String, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (wasmtime::component::__internal::String,), + >::new_unchecked(self.b) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_c( + &self, + mut store: S, + arg0: wasmtime::component::__internal::String, + arg1: wasmtime::component::__internal::String, + ) -> wasmtime::Result< + wasmtime::component::Promise< + wasmtime::component::__internal::String, + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + wasmtime::component::__internal::String, + wasmtime::component::__internal::String, + ), + (wasmtime::component::__internal::String,), + >::new_unchecked(self.c) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0, arg1)) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/strings_tracing_async.rs b/crates/component-macro/tests/expanded/strings_tracing_async.rs index 6e19b15240a3..08862dada894 100644 --- a/crates/component-macro/tests/expanded/strings_tracing_async.rs +++ b/crates/component-macro/tests/expanded/strings_tracing_async.rs @@ -205,19 +205,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/unstable-features.rs b/crates/component-macro/tests/expanded/unstable-features.rs index 9ac28a24a454..f05bf6d923b0 100644 --- a/crates/component-macro/tests/expanded/unstable-features.rs +++ b/crates/component-macro/tests/expanded/unstable-features.rs @@ -62,7 +62,7 @@ impl LinkOptions { } } pub enum Baz {} -pub trait HostBaz { +pub trait HostBaz: Sized { fn foo(&mut self, self_: wasmtime::component::Resource) -> (); fn drop(&mut self, rep: wasmtime::component::Resource) -> wasmtime::Result<()>; } @@ -190,10 +190,11 @@ pub trait TheWorldImports: HostBaz { } pub trait TheWorldImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: TheWorldImports; } -impl TheWorldImportsGetHost for F +impl TheWorldImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: TheWorldImports, @@ -268,10 +269,13 @@ const _: () = { let indices = TheWorldIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost<&'a mut T, T, Host: TheWorldImports>, + >( linker: &mut wasmtime::component::Linker, options: &LinkOptions, - host_getter: impl for<'a> TheWorldImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut linker = linker.root(); if options.experimental_world { @@ -384,7 +388,7 @@ pub mod foo { } } pub enum Bar {} - pub trait HostBar { + pub trait HostBar: Sized { fn foo(&mut self, self_: wasmtime::component::Resource) -> (); fn drop( &mut self, @@ -402,25 +406,29 @@ pub mod foo { HostBar::drop(*self, rep) } } - pub trait Host: HostBar { + pub trait Host: HostBar + Sized { fn foo(&mut self) -> (); } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, options: &LinkOptions, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { if options.experimental_interface { let mut inst = linker.instance("foo:foo/the-interface")?; diff --git a/crates/component-macro/tests/expanded/unstable-features_async.rs b/crates/component-macro/tests/expanded/unstable-features_async.rs index 23686a38346e..f51e3bc86a3a 100644 --- a/crates/component-macro/tests/expanded/unstable-features_async.rs +++ b/crates/component-macro/tests/expanded/unstable-features_async.rs @@ -63,7 +63,7 @@ impl LinkOptions { } pub enum Baz {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] -pub trait HostBaz { +pub trait HostBaz: Sized { async fn foo(&mut self, self_: wasmtime::component::Resource) -> (); async fn drop( &mut self, @@ -201,10 +201,11 @@ pub trait TheWorldImports: Send + HostBaz { } pub trait TheWorldImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: TheWorldImports; } -impl TheWorldImportsGetHost for F +impl TheWorldImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: TheWorldImports, @@ -282,10 +283,13 @@ const _: () = { let indices = TheWorldIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost<&'a mut T, T, Host: TheWorldImports>, + >( linker: &mut wasmtime::component::Linker, options: &LinkOptions, - host_getter: impl for<'a> TheWorldImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -410,7 +414,7 @@ pub mod foo { } pub enum Bar {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostBar { + pub trait HostBar: Sized { async fn foo(&mut self, self_: wasmtime::component::Resource) -> (); async fn drop( &mut self, @@ -432,25 +436,29 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostBar { + pub trait Host: Send + HostBar + Sized { async fn foo(&mut self) -> (); } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, options: &LinkOptions, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/unstable-features_concurrent.rs b/crates/component-macro/tests/expanded/unstable-features_concurrent.rs new file mode 100644 index 000000000000..1fa92826dc03 --- /dev/null +++ b/crates/component-macro/tests/expanded/unstable-features_concurrent.rs @@ -0,0 +1,690 @@ +/// Link-time configurations. +#[derive(Clone, Debug, Default)] +pub struct LinkOptions { + experimental_interface: bool, + experimental_interface_function: bool, + experimental_interface_resource: bool, + experimental_interface_resource_method: bool, + experimental_world: bool, + experimental_world_function_import: bool, + experimental_world_interface_import: bool, + experimental_world_resource: bool, + experimental_world_resource_method: bool, +} +impl LinkOptions { + /// Enable members marked as `@unstable(feature = experimental-interface)` + pub fn experimental_interface(&mut self, enabled: bool) -> &mut Self { + self.experimental_interface = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-interface-function)` + pub fn experimental_interface_function(&mut self, enabled: bool) -> &mut Self { + self.experimental_interface_function = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-interface-resource)` + pub fn experimental_interface_resource(&mut self, enabled: bool) -> &mut Self { + self.experimental_interface_resource = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-interface-resource-method)` + pub fn experimental_interface_resource_method( + &mut self, + enabled: bool, + ) -> &mut Self { + self.experimental_interface_resource_method = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-world)` + pub fn experimental_world(&mut self, enabled: bool) -> &mut Self { + self.experimental_world = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-world-function-import)` + pub fn experimental_world_function_import(&mut self, enabled: bool) -> &mut Self { + self.experimental_world_function_import = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-world-interface-import)` + pub fn experimental_world_interface_import(&mut self, enabled: bool) -> &mut Self { + self.experimental_world_interface_import = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-world-resource)` + pub fn experimental_world_resource(&mut self, enabled: bool) -> &mut Self { + self.experimental_world_resource = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-world-resource-method)` + pub fn experimental_world_resource_method(&mut self, enabled: bool) -> &mut Self { + self.experimental_world_resource_method = enabled; + self + } +} +pub enum Baz {} +pub trait HostBaz: Sized { + type BazData; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::BazData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BazData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn drop(&mut self, rep: wasmtime::component::Resource) -> wasmtime::Result<()>; +} +impl<_T: HostBaz> HostBaz for &mut _T { + type BazData = _T::BazData; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::BazData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BazData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostBaz>::foo(store, self_) + } + fn drop(&mut self, rep: wasmtime::component::Resource) -> wasmtime::Result<()> { + HostBaz::drop(*self, rep) + } +} +impl std::convert::From for foo::foo::the_interface::LinkOptions { + fn from(src: LinkOptions) -> Self { + (&src).into() + } +} +impl std::convert::From<&LinkOptions> for foo::foo::the_interface::LinkOptions { + fn from(src: &LinkOptions) -> Self { + let mut dest = Self::default(); + dest.experimental_interface(src.experimental_interface); + dest.experimental_interface_function(src.experimental_interface_function); + dest.experimental_interface_resource(src.experimental_interface_resource); + dest.experimental_interface_resource_method( + src.experimental_interface_resource_method, + ); + dest + } +} +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `the-world`. +/// +/// This structure is created through [`TheWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`TheWorld`] as well. +pub struct TheWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: TheWorldIndices, +} +impl Clone for TheWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> TheWorldPre<_T> { + /// Creates a new copy of `TheWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`TheWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `the-world`. +/// +/// This is an implementation detail of [`TheWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`TheWorld`] as well. +#[derive(Clone)] +pub struct TheWorldIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `the-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`TheWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`TheWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`TheWorldPre::instantiate_async`] to +/// create a [`TheWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`TheWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`TheWorldIndices::new_instance`] followed +/// by [`TheWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct TheWorld {} +pub trait TheWorldImports: HostBaz { + type Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; +} +pub trait TheWorldImportsGetHost< + T, + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: TheWorldImports; +} +impl TheWorldImportsGetHost for F +where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: TheWorldImports, +{ + type Host = O; +} +impl<_T: TheWorldImports> TheWorldImports for &mut _T { + type Data = _T::Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as TheWorldImports>::foo(store) + } +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl TheWorldIndices { + /// Creates a new copy of `TheWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(TheWorldIndices {}) + } + /// Creates a new instance of [`TheWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`TheWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`TheWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(TheWorldIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`TheWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(TheWorld {}) + } + } + impl TheWorld { + /// Convenience wrapper around [`TheWorldPre::new`] and + /// [`TheWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + TheWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`TheWorldIndices::new_instance`] and + /// [`TheWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = TheWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost< + &'a mut T, + T, + Host: TheWorldImports, + >, + >( + linker: &mut wasmtime::component::Linker, + options: &LinkOptions, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut linker = linker.root(); + if options.experimental_world { + if options.experimental_world_resource { + linker + .resource( + "baz", + wasmtime::component::ResourceType::host::(), + move |mut store, rep| -> wasmtime::Result<()> { + HostBaz::drop( + &mut host_getter(store.data_mut()), + wasmtime::component::Resource::new_own(rep), + ) + }, + )?; + } + if options.experimental_world_function_import { + linker + .func_wrap_concurrent( + "foo", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::foo(host); + Box::pin(async move { + let fun = r.await; + Box::new(move | + mut caller: wasmtime::StoreContextMut<'_, T>| + { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + } + if options.experimental_world_resource_method { + linker + .func_wrap_concurrent( + "[method]baz.foo", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::Resource,)| + { + let host = caller; + let r = ::foo(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move | + mut caller: wasmtime::StoreContextMut<'_, T>| + { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + } + } + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + options: &LinkOptions, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::the_interface::Host + + TheWorldImports + 'static, + U: Send + foo::foo::the_interface::Host + + TheWorldImports, + { + if options.experimental_world { + Self::add_to_linker_imports_get_host(linker, options, get)?; + if options.experimental_world_interface_import { + foo::foo::the_interface::add_to_linker( + linker, + &options.into(), + get, + )?; + } + } + Ok(()) + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod the_interface { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + /// Link-time configurations. + #[derive(Clone, Debug, Default)] + pub struct LinkOptions { + experimental_interface: bool, + experimental_interface_function: bool, + experimental_interface_resource: bool, + experimental_interface_resource_method: bool, + } + impl LinkOptions { + /// Enable members marked as `@unstable(feature = experimental-interface)` + pub fn experimental_interface(&mut self, enabled: bool) -> &mut Self { + self.experimental_interface = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-interface-function)` + pub fn experimental_interface_function( + &mut self, + enabled: bool, + ) -> &mut Self { + self.experimental_interface_function = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-interface-resource)` + pub fn experimental_interface_resource( + &mut self, + enabled: bool, + ) -> &mut Self { + self.experimental_interface_resource = enabled; + self + } + /// Enable members marked as `@unstable(feature = experimental-interface-resource-method)` + pub fn experimental_interface_resource_method( + &mut self, + enabled: bool, + ) -> &mut Self { + self.experimental_interface_resource_method = enabled; + self + } + } + pub enum Bar {} + pub trait HostBar: Sized { + type BarData; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()>; + } + impl<_T: HostBar> HostBar for &mut _T { + type BarData = _T::BarData; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::BarData>, + self_: wasmtime::component::Resource, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::BarData>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as HostBar>::foo(store, self_) + } + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + HostBar::drop(*self, rep) + } + } + pub trait Host: HostBar + Sized { + type Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost< + &'a mut T, + T, + Host: Host + Send, + >, + >( + linker: &mut wasmtime::component::Linker, + options: &LinkOptions, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + if options.experimental_interface { + let mut inst = linker.instance("foo:foo/the-interface")?; + if options.experimental_interface_resource { + inst.resource( + "bar", + wasmtime::component::ResourceType::host::(), + move |mut store, rep| -> wasmtime::Result<()> { + HostBar::drop( + &mut host_getter(store.data_mut()), + wasmtime::component::Resource::new_own(rep), + ) + }, + )?; + } + if options.experimental_interface_function { + inst.func_wrap_concurrent( + "foo", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::foo(host); + Box::pin(async move { + let fun = r.await; + Box::new(move | + mut caller: wasmtime::StoreContextMut<'_, T>| + { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + } + if options.experimental_interface_resource_method { + inst.func_wrap_concurrent( + "[method]bar.foo", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (wasmtime::component::Resource,)| + { + let host = caller; + let r = ::foo(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move | + mut caller: wasmtime::StoreContextMut<'_, T>| + { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + } + } + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + options: &LinkOptions, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, options, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn foo( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::foo(store) + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/unstable-features_tracing_async.rs b/crates/component-macro/tests/expanded/unstable-features_tracing_async.rs index 500bc93d285b..9f0d394a59e9 100644 --- a/crates/component-macro/tests/expanded/unstable-features_tracing_async.rs +++ b/crates/component-macro/tests/expanded/unstable-features_tracing_async.rs @@ -63,7 +63,7 @@ impl LinkOptions { } pub enum Baz {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] -pub trait HostBaz { +pub trait HostBaz: Sized { async fn foo(&mut self, self_: wasmtime::component::Resource) -> (); async fn drop( &mut self, @@ -201,10 +201,11 @@ pub trait TheWorldImports: Send + HostBaz { } pub trait TheWorldImportsGetHost< T, ->: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, +>: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: TheWorldImports; } -impl TheWorldImportsGetHost for F +impl TheWorldImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: TheWorldImports, @@ -282,10 +283,13 @@ const _: () = { let indices = TheWorldIndices::new_instance(&mut store, instance)?; indices.load(store, instance) } - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> TheWorldImportsGetHost<&'a mut T, T, Host: TheWorldImports>, + >( linker: &mut wasmtime::component::Linker, options: &LinkOptions, - host_getter: impl for<'a> TheWorldImportsGetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -439,7 +443,7 @@ pub mod foo { } pub enum Bar {} #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait HostBar { + pub trait HostBar: Sized { async fn foo(&mut self, self_: wasmtime::component::Resource) -> (); async fn drop( &mut self, @@ -461,25 +465,29 @@ pub mod foo { } } #[wasmtime::component::__internal::trait_variant_make(::core::marker::Send)] - pub trait Host: Send + HostBar { + pub trait Host: Send + HostBar + Sized { async fn foo(&mut self) -> (); } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, options: &LinkOptions, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/unversioned-foo.rs b/crates/component-macro/tests/expanded/unversioned-foo.rs index bec71942c97c..3a4d42f9672d 100644 --- a/crates/component-macro/tests/expanded/unversioned-foo.rs +++ b/crates/component-macro/tests/expanded/unversioned-foo.rs @@ -206,19 +206,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/a")?; inst.func_wrap( diff --git a/crates/component-macro/tests/expanded/unversioned-foo_async.rs b/crates/component-macro/tests/expanded/unversioned-foo_async.rs index c7c5c8d9d53a..8a8e8343bf6e 100644 --- a/crates/component-macro/tests/expanded/unversioned-foo_async.rs +++ b/crates/component-macro/tests/expanded/unversioned-foo_async.rs @@ -214,19 +214,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs b/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs new file mode 100644 index 000000000000..75b1b6e10dd5 --- /dev/null +++ b/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs @@ -0,0 +1,306 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `nope`. +/// +/// This structure is created through [`NopePre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Nope`] as well. +pub struct NopePre { + instance_pre: wasmtime::component::InstancePre, + indices: NopeIndices, +} +impl Clone for NopePre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> NopePre<_T> { + /// Creates a new copy of `NopePre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = NopeIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Nope`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `nope`. +/// +/// This is an implementation detail of [`NopePre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Nope`] as well. +#[derive(Clone)] +pub struct NopeIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `nope`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Nope::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`NopePre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`NopePre::instantiate_async`] to +/// create a [`Nope`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Nope::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`NopeIndices::new_instance`] followed +/// by [`NopeIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Nope {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl NopeIndices { + /// Creates a new copy of `NopeIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(NopeIndices {}) + } + /// Creates a new instance of [`NopeIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Nope`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Nope`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(NopeIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Nope`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(Nope {}) + } + } + impl Nope { + /// Convenience wrapper around [`NopePre::new`] and + /// [`NopePre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + NopePre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`NopeIndices::new_instance`] and + /// [`NopeIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = NopeIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::a::Host + 'static, + U: Send + foo::foo::a::Host, + { + foo::foo::a::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod a { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone)] + pub enum Error { + #[component(name = "other")] + Other(wasmtime::component::__internal::String), + } + impl core::fmt::Debug for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Other(e) => { + f.debug_tuple("Error::Other").field(e).finish() + } + } + } + } + impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self) + } + } + impl std::error::Error for Error {} + const _: () = { + assert!(12 == < Error as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Error as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn g( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(), Error> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/a")?; + inst.func_wrap_concurrent( + "g", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::g(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result<(), Error>,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result<(), Error>,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn g( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(), Error> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::g(store) + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/unversioned-foo_tracing_async.rs b/crates/component-macro/tests/expanded/unversioned-foo_tracing_async.rs index 489b1855dd81..4981d18a24ae 100644 --- a/crates/component-macro/tests/expanded/unversioned-foo_tracing_async.rs +++ b/crates/component-macro/tests/expanded/unversioned-foo_tracing_async.rs @@ -214,19 +214,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/use-paths.rs b/crates/component-macro/tests/expanded/use-paths.rs index 10b39e821120..647b0a880919 100644 --- a/crates/component-macro/tests/expanded/use-paths.rs +++ b/crates/component-macro/tests/expanded/use-paths.rs @@ -196,19 +196,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/a")?; inst.func_wrap( @@ -250,19 +254,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/b")?; inst.func_wrap( @@ -304,19 +312,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/c")?; inst.func_wrap( @@ -360,19 +372,20 @@ pub mod d { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host GetHost<&'a mut T, T, Host: Host>>( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("d")?; inst.func_wrap( diff --git a/crates/component-macro/tests/expanded/use-paths_async.rs b/crates/component-macro/tests/expanded/use-paths_async.rs index 43033c158764..3123a45dcc94 100644 --- a/crates/component-macro/tests/expanded/use-paths_async.rs +++ b/crates/component-macro/tests/expanded/use-paths_async.rs @@ -205,19 +205,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -266,19 +270,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -327,19 +335,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -390,19 +402,23 @@ pub mod d { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/use-paths_concurrent.rs b/crates/component-macro/tests/expanded/use-paths_concurrent.rs new file mode 100644 index 000000000000..01d9fd4de122 --- /dev/null +++ b/crates/component-macro/tests/expanded/use-paths_concurrent.rs @@ -0,0 +1,607 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `d`. +/// +/// This structure is created through [`DPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`D`] as well. +pub struct DPre { + instance_pre: wasmtime::component::InstancePre, + indices: DIndices, +} +impl Clone for DPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> DPre<_T> { + /// Creates a new copy of `DPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = DIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`D`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `d`. +/// +/// This is an implementation detail of [`DPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`D`] as well. +#[derive(Clone)] +pub struct DIndices {} +/// Auto-generated bindings for an instance a component which +/// implements the world `d`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`D::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`DPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`DPre::instantiate_async`] to +/// create a [`D`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`D::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`DIndices::new_instance`] followed +/// by [`DIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct D {} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl DIndices { + /// Creates a new copy of `DIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + Ok(DIndices {}) + } + /// Creates a new instance of [`DIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`D`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`D`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(DIndices {}) + } + /// Uses the indices stored in `self` to load an instance + /// of [`D`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + Ok(D {}) + } + } + impl D { + /// Convenience wrapper around [`DPre::new`] and + /// [`DPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + DPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`DIndices::new_instance`] and + /// [`DIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = DIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::a::Host + foo::foo::b::Host + + foo::foo::c::Host + d::Host + 'static, + U: Send + foo::foo::a::Host + foo::foo::b::Host + + foo::foo::c::Host + d::Host, + { + foo::foo::a::add_to_linker(linker, get)?; + foo::foo::b::add_to_linker(linker, get)?; + foo::foo::c::add_to_linker(linker, get)?; + d::add_to_linker(linker, get)?; + Ok(()) + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod a { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct Foo {} + impl core::fmt::Debug for Foo { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Foo").finish() + } + } + const _: () = { + assert!(0 == < Foo as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/a")?; + inst.func_wrap_concurrent( + "a", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::a(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a(store) + } + } + } + #[allow(clippy::all)] + pub mod b { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Foo = super::super::super::foo::foo::a::Foo; + const _: () = { + assert!(0 == < Foo as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/b")?; + inst.func_wrap_concurrent( + "a", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::a(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a(store) + } + } + } + #[allow(clippy::all)] + pub mod c { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Foo = super::super::super::foo::foo::b::Foo; + const _: () = { + assert!(0 == < Foo as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/c")?; + inst.func_wrap_concurrent( + "a", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::a(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn a( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::a(store) + } + } + } + } +} +#[allow(clippy::all)] +pub mod d { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type Foo = super::foo::foo::c::Foo; + const _: () = { + assert!(0 == < Foo as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn b( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("d")?; + inst.func_wrap_concurrent( + "b", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::b(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Foo,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn b( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Foo + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::b(store) + } + } +} diff --git a/crates/component-macro/tests/expanded/use-paths_tracing_async.rs b/crates/component-macro/tests/expanded/use-paths_tracing_async.rs index 6f5f5a69608c..e0ffb652e629 100644 --- a/crates/component-macro/tests/expanded/use-paths_tracing_async.rs +++ b/crates/component-macro/tests/expanded/use-paths_tracing_async.rs @@ -205,19 +205,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -279,19 +283,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -353,19 +361,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, @@ -429,19 +441,23 @@ pub mod d { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/variants.rs b/crates/component-macro/tests/expanded/variants.rs index 86e8d659eae5..ae1b49a17dfe 100644 --- a/crates/component-macro/tests/expanded/variants.rs +++ b/crates/component-macro/tests/expanded/variants.rs @@ -532,19 +532,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/variants")?; inst.func_wrap( @@ -1613,7 +1617,10 @@ pub mod exports { &self, mut store: S, arg0: E1, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (E1,), @@ -1627,7 +1634,10 @@ pub mod exports { pub fn call_e1_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1642,7 +1652,10 @@ pub mod exports { &self, mut store: S, arg0: &V1, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&V1,), @@ -1656,7 +1669,10 @@ pub mod exports { pub fn call_v1_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1671,7 +1687,10 @@ pub mod exports { &self, mut store: S, arg0: bool, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (bool,), @@ -1685,7 +1704,10 @@ pub mod exports { pub fn call_bool_result( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1705,7 +1727,10 @@ pub mod exports { arg3: Option, arg4: Option, arg5: Option>, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< ( @@ -1739,7 +1764,10 @@ pub mod exports { Option, Option>, ), - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1770,7 +1798,10 @@ pub mod exports { arg5: Casts6, ) -> wasmtime::Result< (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6), - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6), @@ -1794,7 +1825,10 @@ pub mod exports { arg3: Result<(), ()>, arg4: Result, arg5: Result<&str, &[u8]>, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< ( @@ -1831,7 +1865,10 @@ pub mod exports { wasmtime::component::__internal::Vec, >, ), - > { + > + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1857,7 +1894,10 @@ pub mod exports { pub fn call_return_result_sugar( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1871,7 +1911,10 @@ pub mod exports { pub fn call_return_result_sugar2( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1885,7 +1928,10 @@ pub mod exports { pub fn call_return_result_sugar3( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1899,7 +1945,10 @@ pub mod exports { pub fn call_return_result_sugar4( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1913,7 +1962,10 @@ pub mod exports { pub fn call_return_option_sugar( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1927,7 +1979,10 @@ pub mod exports { pub fn call_return_option_sugar2( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1941,7 +1996,10 @@ pub mod exports { pub fn call_result_simple( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1956,7 +2014,10 @@ pub mod exports { &self, mut store: S, arg0: &IsClone, - ) -> wasmtime::Result<()> { + ) -> wasmtime::Result<()> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (&IsClone,), @@ -1970,7 +2031,10 @@ pub mod exports { pub fn call_is_clone_return( &self, mut store: S, - ) -> wasmtime::Result { + ) -> wasmtime::Result + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1984,7 +2048,10 @@ pub mod exports { pub fn call_return_named_option( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), @@ -1998,7 +2065,10 @@ pub mod exports { pub fn call_return_named_result( &self, mut store: S, - ) -> wasmtime::Result> { + ) -> wasmtime::Result> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::< (), diff --git a/crates/component-macro/tests/expanded/variants_async.rs b/crates/component-macro/tests/expanded/variants_async.rs index bf9403156018..10da539ad148 100644 --- a/crates/component-macro/tests/expanded/variants_async.rs +++ b/crates/component-macro/tests/expanded/variants_async.rs @@ -540,19 +540,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/variants_concurrent.rs b/crates/component-macro/tests/expanded/variants_concurrent.rs new file mode 100644 index 000000000000..8581cf27ed5a --- /dev/null +++ b/crates/component-macro/tests/expanded/variants_concurrent.rs @@ -0,0 +1,3070 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `my-world`. +/// +/// This structure is created through [`MyWorldPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`MyWorld`] as well. +pub struct MyWorldPre { + instance_pre: wasmtime::component::InstancePre, + indices: MyWorldIndices, +} +impl Clone for MyWorldPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> MyWorldPre<_T> { + /// Creates a new copy of `MyWorldPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = MyWorldIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`MyWorld`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `my-world`. +/// +/// This is an implementation detail of [`MyWorldPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`MyWorld`] as well. +#[derive(Clone)] +pub struct MyWorldIndices { + interface0: exports::foo::foo::variants::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `my-world`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`MyWorld::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`MyWorldPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`MyWorldPre::instantiate_async`] to +/// create a [`MyWorld`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`MyWorld::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`MyWorldIndices::new_instance`] followed +/// by [`MyWorldIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct MyWorld { + interface0: exports::foo::foo::variants::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl MyWorldIndices { + /// Creates a new copy of `MyWorldIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::foo::foo::variants::GuestIndices::new(_component)?; + Ok(MyWorldIndices { interface0 }) + } + /// Creates a new instance of [`MyWorldIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`MyWorld`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`MyWorld`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::foo::foo::variants::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(MyWorldIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`MyWorld`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(MyWorld { interface0 }) + } + } + impl MyWorld { + /// Convenience wrapper around [`MyWorldPre::new`] and + /// [`MyWorldPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + MyWorldPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`MyWorldIndices::new_instance`] and + /// [`MyWorldIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = MyWorldIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::variants::Host + 'static, + U: Send + foo::foo::variants::Host, + { + foo::foo::variants::add_to_linker(linker, get)?; + Ok(()) + } + pub fn foo_foo_variants(&self) -> &exports::foo::foo::variants::Guest { + &self.interface0 + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod variants { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(enum)] + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u8)] + pub enum E1 { + #[component(name = "a")] + A, + } + impl core::fmt::Debug for E1 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + E1::A => f.debug_tuple("E1::A").finish(), + } + } + } + const _: () = { + assert!(1 == < E1 as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < E1 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct Empty {} + impl core::fmt::Debug for Empty { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Empty").finish() + } + } + const _: () = { + assert!(0 == < Empty as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < Empty as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone)] + pub enum V1 { + #[component(name = "a")] + A, + #[component(name = "c")] + C(E1), + #[component(name = "d")] + D(wasmtime::component::__internal::String), + #[component(name = "e")] + E(Empty), + #[component(name = "f")] + F, + #[component(name = "g")] + G(u32), + } + impl core::fmt::Debug for V1 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + V1::A => f.debug_tuple("V1::A").finish(), + V1::C(e) => f.debug_tuple("V1::C").field(e).finish(), + V1::D(e) => f.debug_tuple("V1::D").field(e).finish(), + V1::E(e) => f.debug_tuple("V1::E").field(e).finish(), + V1::F => f.debug_tuple("V1::F").finish(), + V1::G(e) => f.debug_tuple("V1::G").field(e).finish(), + } + } + } + const _: () = { + assert!(12 == < V1 as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < V1 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts1 { + #[component(name = "a")] + A(i32), + #[component(name = "b")] + B(f32), + } + impl core::fmt::Debug for Casts1 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Casts1::A(e) => f.debug_tuple("Casts1::A").field(e).finish(), + Casts1::B(e) => f.debug_tuple("Casts1::B").field(e).finish(), + } + } + } + const _: () = { + assert!(8 == < Casts1 as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Casts1 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts2 { + #[component(name = "a")] + A(f64), + #[component(name = "b")] + B(f32), + } + impl core::fmt::Debug for Casts2 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Casts2::A(e) => f.debug_tuple("Casts2::A").field(e).finish(), + Casts2::B(e) => f.debug_tuple("Casts2::B").field(e).finish(), + } + } + } + const _: () = { + assert!(16 == < Casts2 as wasmtime::component::ComponentType >::SIZE32); + assert!(8 == < Casts2 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts3 { + #[component(name = "a")] + A(f64), + #[component(name = "b")] + B(u64), + } + impl core::fmt::Debug for Casts3 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Casts3::A(e) => f.debug_tuple("Casts3::A").field(e).finish(), + Casts3::B(e) => f.debug_tuple("Casts3::B").field(e).finish(), + } + } + } + const _: () = { + assert!(16 == < Casts3 as wasmtime::component::ComponentType >::SIZE32); + assert!(8 == < Casts3 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts4 { + #[component(name = "a")] + A(u32), + #[component(name = "b")] + B(i64), + } + impl core::fmt::Debug for Casts4 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Casts4::A(e) => f.debug_tuple("Casts4::A").field(e).finish(), + Casts4::B(e) => f.debug_tuple("Casts4::B").field(e).finish(), + } + } + } + const _: () = { + assert!(16 == < Casts4 as wasmtime::component::ComponentType >::SIZE32); + assert!(8 == < Casts4 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts5 { + #[component(name = "a")] + A(f32), + #[component(name = "b")] + B(i64), + } + impl core::fmt::Debug for Casts5 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Casts5::A(e) => f.debug_tuple("Casts5::A").field(e).finish(), + Casts5::B(e) => f.debug_tuple("Casts5::B").field(e).finish(), + } + } + } + const _: () = { + assert!(16 == < Casts5 as wasmtime::component::ComponentType >::SIZE32); + assert!(8 == < Casts5 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts6 { + #[component(name = "a")] + A((f32, u32)), + #[component(name = "b")] + B((u32, u32)), + } + impl core::fmt::Debug for Casts6 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Casts6::A(e) => f.debug_tuple("Casts6::A").field(e).finish(), + Casts6::B(e) => f.debug_tuple("Casts6::B").field(e).finish(), + } + } + } + const _: () = { + assert!(12 == < Casts6 as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < Casts6 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(enum)] + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u8)] + pub enum MyErrno { + #[component(name = "bad1")] + Bad1, + #[component(name = "bad2")] + Bad2, + } + impl MyErrno { + pub fn name(&self) -> &'static str { + match self { + MyErrno::Bad1 => "bad1", + MyErrno::Bad2 => "bad2", + } + } + pub fn message(&self) -> &'static str { + match self { + MyErrno::Bad1 => "", + MyErrno::Bad2 => "", + } + } + } + impl core::fmt::Debug for MyErrno { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("MyErrno") + .field("code", &(*self as i32)) + .field("name", &self.name()) + .field("message", &self.message()) + .finish() + } + } + impl core::fmt::Display for MyErrno { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{} (error {})", self.name(), * self as i32) + } + } + impl std::error::Error for MyErrno {} + const _: () = { + assert!(1 == < MyErrno as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < MyErrno as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct IsClone { + #[component(name = "v1")] + pub v1: V1, + } + impl core::fmt::Debug for IsClone { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("IsClone").field("v1", &self.v1).finish() + } + } + const _: () = { + assert!(12 == < IsClone as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < IsClone as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host { + type Data; + fn e1_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: E1, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn e1_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> E1 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn v1_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: V1, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn v1_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> V1 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn bool_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: bool, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn bool_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> bool + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn option_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: Option, + b: Option<()>, + c: Option, + d: Option, + e: Option, + g: Option>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn option_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn casts( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: Casts1, + b: Casts2, + c: Casts3, + d: Casts4, + e: Casts5, + f: Casts6, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + Casts1, + Casts2, + Casts3, + Casts4, + Casts5, + Casts6, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn result_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: Result<(), ()>, + b: Result<(), E1>, + c: Result, + d: Result<(), ()>, + e: Result, + f: Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn result_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_result_sugar( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_result_sugar2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(), MyErrno> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_result_sugar3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_result_sugar4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(i32, u32), MyErrno> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_option_sugar( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_option_sugar2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn result_simple( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn is_clone_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: IsClone, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn is_clone_return( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> IsClone + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_named_option( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + fn return_named_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized; + } + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/variants")?; + inst.func_wrap_concurrent( + "e1-arg", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (E1,)| { + let host = caller; + let r = ::e1_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "e1-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::e1_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(E1,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(E1,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "v1-arg", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (V1,)| { + let host = caller; + let r = ::v1_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "v1-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::v1_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(V1,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(V1,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "bool-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (bool,)| + { + let host = caller; + let r = ::bool_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "bool-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::bool_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(bool,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(bool,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "option-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ): ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + )| + { + let host = caller; + let r = ::option_arg( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "option-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::option_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ), + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ), + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "casts", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ): (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6)| + { + let host = caller; + let r = ::casts( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ((Casts1, Casts2, Casts3, Casts4, Casts5, Casts6),), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ((Casts1, Casts2, Casts3, Casts4, Casts5, Casts6),), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "result-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + ( + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ): ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + )| + { + let host = caller; + let r = ::result_arg( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "result-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::result_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ), + ), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + ( + ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ), + ), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-result-sugar", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_result_sugar(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-result-sugar2", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_result_sugar2(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result<(), MyErrno>,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result<(), MyErrno>,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-result-sugar3", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_result_sugar3(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-result-sugar4", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_result_sugar4(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result<(i32, u32), MyErrno>,), + > + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result< + (Result<(i32, u32), MyErrno>,), + > + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-option-sugar", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_option_sugar(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Option,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Option,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-option-sugar2", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_option_sugar2(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Option,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Option,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "result-simple", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::result_simple(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "is-clone-arg", + move | + mut caller: wasmtime::StoreContextMut<'_, T>, + (arg0,): (IsClone,)| + { + let host = caller; + let r = ::is_clone_arg(host, arg0); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok(r) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<()> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "is-clone-return", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::is_clone_return(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(IsClone,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(IsClone,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-named-option", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_named_option(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Option,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Option,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + inst.func_wrap_concurrent( + "return-named-result", + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + let host = caller; + let r = ::return_named_result(host); + Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + Ok((r,)) + }) + as Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result,)> + Send + Sync, + > + }) + as ::std::pin::Pin< + Box< + dyn ::std::future::Future< + Output = Box< + dyn FnOnce( + wasmtime::StoreContextMut<'_, T>, + ) -> wasmtime::Result<(Result,)> + Send + Sync, + >, + > + Send + Sync + 'static, + >, + > + }, + )?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host> Host for &mut _T { + type Data = _T::Data; + fn e1_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: E1, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::e1_arg(store, x) + } + fn e1_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> E1 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::e1_result(store) + } + fn v1_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: V1, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::v1_arg(store, x) + } + fn v1_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> V1 + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::v1_result(store) + } + fn bool_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + x: bool, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::bool_arg(store, x) + } + fn bool_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> bool + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::bool_result(store) + } + fn option_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: Option, + b: Option<()>, + c: Option, + d: Option, + e: Option, + g: Option>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::option_arg(store, a, b, c, d, e, g) + } + fn option_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::option_result(store) + } + fn casts( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: Casts1, + b: Casts2, + c: Casts3, + d: Casts4, + e: Casts5, + f: Casts6, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + Casts1, + Casts2, + Casts3, + Casts4, + Casts5, + Casts6, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::casts(store, a, b, c, d, e, f) + } + fn result_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: Result<(), ()>, + b: Result<(), E1>, + c: Result, + d: Result<(), ()>, + e: Result, + f: Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::result_arg(store, a, b, c, d, e, f) + } + fn result_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ) + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::result_result(store) + } + fn return_result_sugar( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_result_sugar(store) + } + fn return_result_sugar2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(), MyErrno> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_result_sugar2(store) + } + fn return_result_sugar3( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_result_sugar3(store) + } + fn return_result_sugar4( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result<(i32, u32), MyErrno> + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_result_sugar4(store) + } + fn return_option_sugar( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_option_sugar(store) + } + fn return_option_sugar2( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_option_sugar2(store) + } + fn result_simple( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::result_simple(store) + } + fn is_clone_arg( + store: wasmtime::StoreContextMut<'_, Self::Data>, + a: IsClone, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> () + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::is_clone_arg(store, a) + } + fn is_clone_return( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> IsClone + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::is_clone_return(store) + } + fn return_named_option( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Option + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_named_option(store) + } + fn return_named_result( + store: wasmtime::StoreContextMut<'_, Self::Data>, + ) -> impl ::std::future::Future< + Output = impl FnOnce( + wasmtime::StoreContextMut<'_, Self::Data>, + ) -> Result + Send + Sync + 'static, + > + Send + Sync + 'static + where + Self: Sized, + { + <_T as Host>::return_named_result(store) + } + } + } + } +} +pub mod exports { + pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod variants { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(enum)] + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u8)] + pub enum E1 { + #[component(name = "a")] + A, + } + impl core::fmt::Debug for E1 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + E1::A => f.debug_tuple("E1::A").finish(), + } + } + } + const _: () = { + assert!(1 == < E1 as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < E1 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone, Copy)] + pub struct Empty {} + impl core::fmt::Debug for Empty { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("Empty").finish() + } + } + const _: () = { + assert!( + 0 == < Empty as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < Empty as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone)] + pub enum V1 { + #[component(name = "a")] + A, + #[component(name = "c")] + C(E1), + #[component(name = "d")] + D(wasmtime::component::__internal::String), + #[component(name = "e")] + E(Empty), + #[component(name = "f")] + F, + #[component(name = "g")] + G(u32), + } + impl core::fmt::Debug for V1 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + V1::A => f.debug_tuple("V1::A").finish(), + V1::C(e) => f.debug_tuple("V1::C").field(e).finish(), + V1::D(e) => f.debug_tuple("V1::D").field(e).finish(), + V1::E(e) => f.debug_tuple("V1::E").field(e).finish(), + V1::F => f.debug_tuple("V1::F").finish(), + V1::G(e) => f.debug_tuple("V1::G").field(e).finish(), + } + } + } + const _: () = { + assert!(12 == < V1 as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < V1 as wasmtime::component::ComponentType >::ALIGN32); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts1 { + #[component(name = "a")] + A(i32), + #[component(name = "b")] + B(f32), + } + impl core::fmt::Debug for Casts1 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + Casts1::A(e) => f.debug_tuple("Casts1::A").field(e).finish(), + Casts1::B(e) => f.debug_tuple("Casts1::B").field(e).finish(), + } + } + } + const _: () = { + assert!( + 8 == < Casts1 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < Casts1 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts2 { + #[component(name = "a")] + A(f64), + #[component(name = "b")] + B(f32), + } + impl core::fmt::Debug for Casts2 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + Casts2::A(e) => f.debug_tuple("Casts2::A").field(e).finish(), + Casts2::B(e) => f.debug_tuple("Casts2::B").field(e).finish(), + } + } + } + const _: () = { + assert!( + 16 == < Casts2 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 8 == < Casts2 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts3 { + #[component(name = "a")] + A(f64), + #[component(name = "b")] + B(u64), + } + impl core::fmt::Debug for Casts3 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + Casts3::A(e) => f.debug_tuple("Casts3::A").field(e).finish(), + Casts3::B(e) => f.debug_tuple("Casts3::B").field(e).finish(), + } + } + } + const _: () = { + assert!( + 16 == < Casts3 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 8 == < Casts3 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts4 { + #[component(name = "a")] + A(u32), + #[component(name = "b")] + B(i64), + } + impl core::fmt::Debug for Casts4 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + Casts4::A(e) => f.debug_tuple("Casts4::A").field(e).finish(), + Casts4::B(e) => f.debug_tuple("Casts4::B").field(e).finish(), + } + } + } + const _: () = { + assert!( + 16 == < Casts4 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 8 == < Casts4 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts5 { + #[component(name = "a")] + A(f32), + #[component(name = "b")] + B(i64), + } + impl core::fmt::Debug for Casts5 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + Casts5::A(e) => f.debug_tuple("Casts5::A").field(e).finish(), + Casts5::B(e) => f.debug_tuple("Casts5::B").field(e).finish(), + } + } + } + const _: () = { + assert!( + 16 == < Casts5 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 8 == < Casts5 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(variant)] + #[derive(Clone, Copy)] + pub enum Casts6 { + #[component(name = "a")] + A((f32, u32)), + #[component(name = "b")] + B((u32, u32)), + } + impl core::fmt::Debug for Casts6 { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match self { + Casts6::A(e) => f.debug_tuple("Casts6::A").field(e).finish(), + Casts6::B(e) => f.debug_tuple("Casts6::B").field(e).finish(), + } + } + } + const _: () = { + assert!( + 12 == < Casts6 as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < Casts6 as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(enum)] + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u8)] + pub enum MyErrno { + #[component(name = "bad1")] + Bad1, + #[component(name = "bad2")] + Bad2, + } + impl MyErrno { + pub fn name(&self) -> &'static str { + match self { + MyErrno::Bad1 => "bad1", + MyErrno::Bad2 => "bad2", + } + } + pub fn message(&self) -> &'static str { + match self { + MyErrno::Bad1 => "", + MyErrno::Bad2 => "", + } + } + } + impl core::fmt::Debug for MyErrno { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("MyErrno") + .field("code", &(*self as i32)) + .field("name", &self.name()) + .field("message", &self.message()) + .finish() + } + } + impl core::fmt::Display for MyErrno { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + write!(f, "{} (error {})", self.name(), * self as i32) + } + } + impl std::error::Error for MyErrno {} + const _: () = { + assert!( + 1 == < MyErrno as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 1 == < MyErrno as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + #[derive(wasmtime::component::ComponentType)] + #[derive(wasmtime::component::Lift)] + #[derive(wasmtime::component::Lower)] + #[component(record)] + #[derive(Clone)] + pub struct IsClone { + #[component(name = "v1")] + pub v1: V1, + } + impl core::fmt::Debug for IsClone { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("IsClone").field("v1", &self.v1).finish() + } + } + const _: () = { + assert!( + 12 == < IsClone as wasmtime::component::ComponentType >::SIZE32 + ); + assert!( + 4 == < IsClone as wasmtime::component::ComponentType >::ALIGN32 + ); + }; + pub struct Guest { + e1_arg: wasmtime::component::Func, + e1_result: wasmtime::component::Func, + v1_arg: wasmtime::component::Func, + v1_result: wasmtime::component::Func, + bool_arg: wasmtime::component::Func, + bool_result: wasmtime::component::Func, + option_arg: wasmtime::component::Func, + option_result: wasmtime::component::Func, + casts: wasmtime::component::Func, + result_arg: wasmtime::component::Func, + result_result: wasmtime::component::Func, + return_result_sugar: wasmtime::component::Func, + return_result_sugar2: wasmtime::component::Func, + return_result_sugar3: wasmtime::component::Func, + return_result_sugar4: wasmtime::component::Func, + return_option_sugar: wasmtime::component::Func, + return_option_sugar2: wasmtime::component::Func, + result_simple: wasmtime::component::Func, + is_clone_arg: wasmtime::component::Func, + is_clone_return: wasmtime::component::Func, + return_named_option: wasmtime::component::Func, + return_named_result: wasmtime::component::Func, + } + #[derive(Clone)] + pub struct GuestIndices { + e1_arg: wasmtime::component::ComponentExportIndex, + e1_result: wasmtime::component::ComponentExportIndex, + v1_arg: wasmtime::component::ComponentExportIndex, + v1_result: wasmtime::component::ComponentExportIndex, + bool_arg: wasmtime::component::ComponentExportIndex, + bool_result: wasmtime::component::ComponentExportIndex, + option_arg: wasmtime::component::ComponentExportIndex, + option_result: wasmtime::component::ComponentExportIndex, + casts: wasmtime::component::ComponentExportIndex, + result_arg: wasmtime::component::ComponentExportIndex, + result_result: wasmtime::component::ComponentExportIndex, + return_result_sugar: wasmtime::component::ComponentExportIndex, + return_result_sugar2: wasmtime::component::ComponentExportIndex, + return_result_sugar3: wasmtime::component::ComponentExportIndex, + return_result_sugar4: wasmtime::component::ComponentExportIndex, + return_option_sugar: wasmtime::component::ComponentExportIndex, + return_option_sugar2: wasmtime::component::ComponentExportIndex, + result_simple: wasmtime::component::ComponentExportIndex, + is_clone_arg: wasmtime::component::ComponentExportIndex, + is_clone_return: wasmtime::component::ComponentExportIndex, + return_named_option: wasmtime::component::ComponentExportIndex, + return_named_result: wasmtime::component::ComponentExportIndex, + } + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "foo:foo/variants") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/variants`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export(&mut store, None, "foo:foo/variants") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `foo:foo/variants`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `foo:foo/variants` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + let e1_arg = lookup("e1-arg")?; + let e1_result = lookup("e1-result")?; + let v1_arg = lookup("v1-arg")?; + let v1_result = lookup("v1-result")?; + let bool_arg = lookup("bool-arg")?; + let bool_result = lookup("bool-result")?; + let option_arg = lookup("option-arg")?; + let option_result = lookup("option-result")?; + let casts = lookup("casts")?; + let result_arg = lookup("result-arg")?; + let result_result = lookup("result-result")?; + let return_result_sugar = lookup("return-result-sugar")?; + let return_result_sugar2 = lookup("return-result-sugar2")?; + let return_result_sugar3 = lookup("return-result-sugar3")?; + let return_result_sugar4 = lookup("return-result-sugar4")?; + let return_option_sugar = lookup("return-option-sugar")?; + let return_option_sugar2 = lookup("return-option-sugar2")?; + let result_simple = lookup("result-simple")?; + let is_clone_arg = lookup("is-clone-arg")?; + let is_clone_return = lookup("is-clone-return")?; + let return_named_option = lookup("return-named-option")?; + let return_named_result = lookup("return-named-result")?; + Ok(GuestIndices { + e1_arg, + e1_result, + v1_arg, + v1_result, + bool_arg, + bool_result, + option_arg, + option_result, + casts, + result_arg, + result_result, + return_result_sugar, + return_result_sugar2, + return_result_sugar3, + return_result_sugar4, + return_option_sugar, + return_option_sugar2, + result_simple, + is_clone_arg, + is_clone_return, + return_named_option, + return_named_result, + }) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + let e1_arg = *_instance + .get_typed_func::<(E1,), ()>(&mut store, &self.e1_arg)? + .func(); + let e1_result = *_instance + .get_typed_func::<(), (E1,)>(&mut store, &self.e1_result)? + .func(); + let v1_arg = *_instance + .get_typed_func::<(&V1,), ()>(&mut store, &self.v1_arg)? + .func(); + let v1_result = *_instance + .get_typed_func::<(), (V1,)>(&mut store, &self.v1_result)? + .func(); + let bool_arg = *_instance + .get_typed_func::<(bool,), ()>(&mut store, &self.bool_arg)? + .func(); + let bool_result = *_instance + .get_typed_func::< + (), + (bool,), + >(&mut store, &self.bool_result)? + .func(); + let option_arg = *_instance + .get_typed_func::< + ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ), + (), + >(&mut store, &self.option_arg)? + .func(); + let option_result = *_instance + .get_typed_func::< + (), + ( + ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ), + ), + >(&mut store, &self.option_result)? + .func(); + let casts = *_instance + .get_typed_func::< + (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6), + ((Casts1, Casts2, Casts3, Casts4, Casts5, Casts6),), + >(&mut store, &self.casts)? + .func(); + let result_arg = *_instance + .get_typed_func::< + ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result<&str, &[u8]>, + ), + (), + >(&mut store, &self.result_arg)? + .func(); + let result_result = *_instance + .get_typed_func::< + (), + ( + ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ), + ), + >(&mut store, &self.result_result)? + .func(); + let return_result_sugar = *_instance + .get_typed_func::< + (), + (Result,), + >(&mut store, &self.return_result_sugar)? + .func(); + let return_result_sugar2 = *_instance + .get_typed_func::< + (), + (Result<(), MyErrno>,), + >(&mut store, &self.return_result_sugar2)? + .func(); + let return_result_sugar3 = *_instance + .get_typed_func::< + (), + (Result,), + >(&mut store, &self.return_result_sugar3)? + .func(); + let return_result_sugar4 = *_instance + .get_typed_func::< + (), + (Result<(i32, u32), MyErrno>,), + >(&mut store, &self.return_result_sugar4)? + .func(); + let return_option_sugar = *_instance + .get_typed_func::< + (), + (Option,), + >(&mut store, &self.return_option_sugar)? + .func(); + let return_option_sugar2 = *_instance + .get_typed_func::< + (), + (Option,), + >(&mut store, &self.return_option_sugar2)? + .func(); + let result_simple = *_instance + .get_typed_func::< + (), + (Result,), + >(&mut store, &self.result_simple)? + .func(); + let is_clone_arg = *_instance + .get_typed_func::< + (&IsClone,), + (), + >(&mut store, &self.is_clone_arg)? + .func(); + let is_clone_return = *_instance + .get_typed_func::< + (), + (IsClone,), + >(&mut store, &self.is_clone_return)? + .func(); + let return_named_option = *_instance + .get_typed_func::< + (), + (Option,), + >(&mut store, &self.return_named_option)? + .func(); + let return_named_result = *_instance + .get_typed_func::< + (), + (Result,), + >(&mut store, &self.return_named_result)? + .func(); + Ok(Guest { + e1_arg, + e1_result, + v1_arg, + v1_result, + bool_arg, + bool_result, + option_arg, + option_result, + casts, + result_arg, + result_result, + return_result_sugar, + return_result_sugar2, + return_result_sugar3, + return_result_sugar4, + return_option_sugar, + return_option_sugar2, + result_simple, + is_clone_arg, + is_clone_return, + return_named_option, + return_named_result, + }) + } + } + impl Guest { + pub async fn call_e1_arg( + &self, + mut store: S, + arg0: E1, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (E1,), + (), + >::new_unchecked(self.e1_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_e1_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (E1,), + >::new_unchecked(self.e1_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_v1_arg( + &self, + mut store: S, + arg0: V1, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (V1,), + (), + >::new_unchecked(self.v1_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_v1_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (V1,), + >::new_unchecked(self.v1_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_bool_arg( + &self, + mut store: S, + arg0: bool, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (bool,), + (), + >::new_unchecked(self.bool_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_bool_result( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (bool,), + >::new_unchecked(self.bool_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_option_arg( + &self, + mut store: S, + arg0: Option, + arg1: Option<()>, + arg2: Option, + arg3: Option, + arg4: Option, + arg5: Option>, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ), + (), + >::new_unchecked(self.option_arg) + }; + let promise = callee + .call_concurrent( + store.as_context_mut(), + (arg0, arg1, arg2, arg3, arg4, arg5), + ) + .await?; + Ok(promise) + } + pub async fn call_option_result( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ), + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + ( + ( + Option, + Option<()>, + Option, + Option, + Option, + Option>, + ), + ), + >::new_unchecked(self.option_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_casts( + &self, + mut store: S, + arg0: Casts1, + arg1: Casts2, + arg2: Casts3, + arg3: Casts4, + arg4: Casts5, + arg5: Casts6, + ) -> wasmtime::Result< + wasmtime::component::Promise< + (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6), + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6), + ((Casts1, Casts2, Casts3, Casts4, Casts5, Casts6),), + >::new_unchecked(self.casts) + }; + let promise = callee + .call_concurrent( + store.as_context_mut(), + (arg0, arg1, arg2, arg3, arg4, arg5), + ) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_result_arg( + &self, + mut store: S, + arg0: Result<(), ()>, + arg1: Result<(), E1>, + arg2: Result, + arg3: Result<(), ()>, + arg4: Result, + arg5: Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ), + (), + >::new_unchecked(self.result_arg) + }; + let promise = callee + .call_concurrent( + store.as_context_mut(), + (arg0, arg1, arg2, arg3, arg4, arg5), + ) + .await?; + Ok(promise) + } + pub async fn call_result_result( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise< + ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ), + >, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + ( + ( + Result<(), ()>, + Result<(), E1>, + Result, + Result<(), ()>, + Result, + Result< + wasmtime::component::__internal::String, + wasmtime::component::__internal::Vec, + >, + ), + ), + >::new_unchecked(self.result_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_result_sugar( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Result,), + >::new_unchecked(self.return_result_sugar) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_result_sugar2( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Result<(), MyErrno>,), + >::new_unchecked(self.return_result_sugar2) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_result_sugar3( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Result,), + >::new_unchecked(self.return_result_sugar3) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_result_sugar4( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Result<(i32, u32), MyErrno>,), + >::new_unchecked(self.return_result_sugar4) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_option_sugar( + &self, + mut store: S, + ) -> wasmtime::Result>> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Option,), + >::new_unchecked(self.return_option_sugar) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_option_sugar2( + &self, + mut store: S, + ) -> wasmtime::Result>> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Option,), + >::new_unchecked(self.return_option_sugar2) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_result_simple( + &self, + mut store: S, + ) -> wasmtime::Result>> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Result,), + >::new_unchecked(self.result_simple) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_is_clone_arg( + &self, + mut store: S, + arg0: IsClone, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (IsClone,), + (), + >::new_unchecked(self.is_clone_arg) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), (arg0,)) + .await?; + Ok(promise) + } + pub async fn call_is_clone_return( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (IsClone,), + >::new_unchecked(self.is_clone_return) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_named_option( + &self, + mut store: S, + ) -> wasmtime::Result>> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Option,), + >::new_unchecked(self.return_named_option) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + pub async fn call_return_named_result( + &self, + mut store: S, + ) -> wasmtime::Result< + wasmtime::component::Promise>, + > + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::< + (), + (Result,), + >::new_unchecked(self.return_named_result) + }; + let promise = callee + .call_concurrent(store.as_context_mut(), ()) + .await?; + Ok(promise.map(|(v,)| v)) + } + } + } + } + } +} diff --git a/crates/component-macro/tests/expanded/variants_tracing_async.rs b/crates/component-macro/tests/expanded/variants_tracing_async.rs index 089de949b552..4c8f335ccb82 100644 --- a/crates/component-macro/tests/expanded/variants_tracing_async.rs +++ b/crates/component-macro/tests/expanded/variants_tracing_async.rs @@ -540,19 +540,23 @@ pub mod foo { } pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/wat_concurrent.rs b/crates/component-macro/tests/expanded/wat_concurrent.rs new file mode 100644 index 000000000000..cbe5e2e19257 --- /dev/null +++ b/crates/component-macro/tests/expanded/wat_concurrent.rs @@ -0,0 +1,271 @@ +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `example`. +/// +/// This structure is created through [`ExamplePre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Example`] as well. +pub struct ExamplePre { + instance_pre: wasmtime::component::InstancePre, + indices: ExampleIndices, +} +impl Clone for ExamplePre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> ExamplePre<_T> { + /// Creates a new copy of `ExamplePre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = ExampleIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Example`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `example`. +/// +/// This is an implementation detail of [`ExamplePre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Example`] as well. +#[derive(Clone)] +pub struct ExampleIndices { + interface0: exports::same::name::this_name_is_duplicated::GuestIndices, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `example`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Example::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`ExamplePre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`ExamplePre::instantiate_async`] to +/// create a [`Example`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Example::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`ExampleIndices::new_instance`] followed +/// by [`ExampleIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Example { + interface0: exports::same::name::this_name_is_duplicated::Guest, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl ExampleIndices { + /// Creates a new copy of `ExampleIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let interface0 = exports::same::name::this_name_is_duplicated::GuestIndices::new( + _component, + )?; + Ok(ExampleIndices { interface0 }) + } + /// Creates a new instance of [`ExampleIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Example`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Example`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = exports::same::name::this_name_is_duplicated::GuestIndices::new_instance( + &mut store, + _instance, + )?; + Ok(ExampleIndices { interface0 }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Example`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let interface0 = self.interface0.load(&mut store, &_instance)?; + Ok(Example { interface0 }) + } + } + impl Example { + /// Convenience wrapper around [`ExamplePre::new`] and + /// [`ExamplePre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + ExamplePre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`ExampleIndices::new_instance`] and + /// [`ExampleIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = ExampleIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn same_name_this_name_is_duplicated( + &self, + ) -> &exports::same::name::this_name_is_duplicated::Guest { + &self.interface0 + } + } +}; +pub mod exports { + pub mod same { + pub mod name { + #[allow(clippy::all)] + pub mod this_name_is_duplicated { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type ThisNameIsDuplicated = wasmtime::component::ResourceAny; + pub struct GuestThisNameIsDuplicated<'a> { + funcs: &'a Guest, + } + pub struct Guest {} + #[derive(Clone)] + pub struct GuestIndices {} + impl GuestIndices { + /// Constructor for [`GuestIndices`] which takes a + /// [`Component`](wasmtime::component::Component) as input and can be executed + /// before instantiation. + /// + /// This constructor can be used to front-load string lookups to find exports + /// within a component. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let (_, instance) = component + .export_index(None, "same:name/this-name-is-duplicated") + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `same:name/this-name-is-duplicated`" + ) + })?; + Self::_new(|name| { + component.export_index(Some(&instance), name).map(|p| p.1) + }) + } + /// This constructor is similar to [`GuestIndices::new`] except that it + /// performs string lookups after instantiation time. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let instance_export = instance + .get_export( + &mut store, + None, + "same:name/this-name-is-duplicated", + ) + .ok_or_else(|| { + anyhow::anyhow!( + "no exported instance named `same:name/this-name-is-duplicated`" + ) + })?; + Self::_new(|name| { + instance.get_export(&mut store, Some(&instance_export), name) + }) + } + fn _new( + mut lookup: impl FnMut( + &str, + ) -> Option, + ) -> wasmtime::Result { + let mut lookup = move |name| { + lookup(name) + .ok_or_else(|| { + anyhow::anyhow!( + "instance export `same:name/this-name-is-duplicated` does \ + not have export `{name}`" + ) + }) + }; + let _ = &mut lookup; + Ok(GuestIndices {}) + } + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let mut store = store.as_context_mut(); + let _ = &mut store; + let _instance = instance; + Ok(Guest {}) + } + } + impl Guest {} + } + } + } +} diff --git a/crates/component-macro/tests/expanded/worlds-with-types.rs b/crates/component-macro/tests/expanded/worlds-with-types.rs index 216976fd4272..3d3486728f58 100644 --- a/crates/component-macro/tests/expanded/worlds-with-types.rs +++ b/crates/component-macro/tests/expanded/worlds-with-types.rs @@ -207,7 +207,10 @@ const _: () = { pub fn call_f( &self, mut store: S, - ) -> wasmtime::Result<(T, U, R)> { + ) -> wasmtime::Result<(T, U, R)> + where + ::Data: Send, + { let callee = unsafe { wasmtime::component::TypedFunc::<(), ((T, U, R),)>::new_unchecked(self.f) }; @@ -231,19 +234,23 @@ pub mod foo { pub trait Host {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> { let mut inst = linker.instance("foo:foo/i")?; Ok(()) diff --git a/crates/component-macro/tests/expanded/worlds-with-types_async.rs b/crates/component-macro/tests/expanded/worlds-with-types_async.rs index c5c1b0f3f6c0..74cfd8ff3d2c 100644 --- a/crates/component-macro/tests/expanded/worlds-with-types_async.rs +++ b/crates/component-macro/tests/expanded/worlds-with-types_async.rs @@ -242,19 +242,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/component-macro/tests/expanded/worlds-with-types_concurrent.rs b/crates/component-macro/tests/expanded/worlds-with-types_concurrent.rs new file mode 100644 index 000000000000..86fee0cb2901 --- /dev/null +++ b/crates/component-macro/tests/expanded/worlds-with-types_concurrent.rs @@ -0,0 +1,280 @@ +pub type U = foo::foo::i::T; +const _: () = { + assert!(2 == < U as wasmtime::component::ComponentType >::SIZE32); + assert!(2 == < U as wasmtime::component::ComponentType >::ALIGN32); +}; +pub type T = u32; +const _: () = { + assert!(4 == < T as wasmtime::component::ComponentType >::SIZE32); + assert!(4 == < T as wasmtime::component::ComponentType >::ALIGN32); +}; +#[derive(wasmtime::component::ComponentType)] +#[derive(wasmtime::component::Lift)] +#[derive(wasmtime::component::Lower)] +#[component(record)] +#[derive(Clone, Copy)] +pub struct R {} +impl core::fmt::Debug for R { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("R").finish() + } +} +const _: () = { + assert!(0 == < R as wasmtime::component::ComponentType >::SIZE32); + assert!(1 == < R as wasmtime::component::ComponentType >::ALIGN32); +}; +/// Auto-generated bindings for a pre-instantiated version of a +/// component which implements the world `foo`. +/// +/// This structure is created through [`FooPre::new`] which +/// takes a [`InstancePre`](wasmtime::component::InstancePre) that +/// has been created through a [`Linker`](wasmtime::component::Linker). +/// +/// For more information see [`Foo`] as well. +pub struct FooPre { + instance_pre: wasmtime::component::InstancePre, + indices: FooIndices, +} +impl Clone for FooPre { + fn clone(&self) -> Self { + Self { + instance_pre: self.instance_pre.clone(), + indices: self.indices.clone(), + } + } +} +impl<_T> FooPre<_T> { + /// Creates a new copy of `FooPre` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component behind `instance_pre` + /// does not have the required exports. + pub fn new( + instance_pre: wasmtime::component::InstancePre<_T>, + ) -> wasmtime::Result { + let indices = FooIndices::new(instance_pre.component())?; + Ok(Self { instance_pre, indices }) + } + pub fn engine(&self) -> &wasmtime::Engine { + self.instance_pre.engine() + } + pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { + &self.instance_pre + } + /// Instantiates a new instance of [`Foo`] within the + /// `store` provided. + /// + /// This function will use `self` as the pre-instantiated + /// instance to perform instantiation. Afterwards the preloaded + /// indices in `self` are used to lookup all exports on the + /// resulting instance. + pub async fn instantiate_async( + &self, + mut store: impl wasmtime::AsContextMut, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let mut store = store.as_context_mut(); + let instance = self.instance_pre.instantiate_async(&mut store).await?; + self.indices.load(&mut store, &instance) + } +} +/// Auto-generated bindings for index of the exports of +/// `foo`. +/// +/// This is an implementation detail of [`FooPre`] and can +/// be constructed if needed as well. +/// +/// For more information see [`Foo`] as well. +#[derive(Clone)] +pub struct FooIndices { + f: wasmtime::component::ComponentExportIndex, +} +/// Auto-generated bindings for an instance a component which +/// implements the world `foo`. +/// +/// This structure can be created through a number of means +/// depending on your requirements and what you have on hand: +/// +/// * The most convenient way is to use +/// [`Foo::instantiate_async`] which only needs a +/// [`Store`], [`Component`], and [`Linker`]. +/// +/// * Alternatively you can create a [`FooPre`] ahead of +/// time with a [`Component`] to front-load string lookups +/// of exports once instead of per-instantiation. This +/// method then uses [`FooPre::instantiate_async`] to +/// create a [`Foo`]. +/// +/// * If you've instantiated the instance yourself already +/// then you can use [`Foo::new`]. +/// +/// * You can also access the guts of instantiation through +/// [`FooIndices::new_instance`] followed +/// by [`FooIndices::load`] to crate an instance of this +/// type. +/// +/// These methods are all equivalent to one another and move +/// around the tradeoff of what work is performed when. +/// +/// [`Store`]: wasmtime::Store +/// [`Component`]: wasmtime::component::Component +/// [`Linker`]: wasmtime::component::Linker +pub struct Foo { + f: wasmtime::component::Func, +} +const _: () = { + #[allow(unused_imports)] + use wasmtime::component::__internal::anyhow; + impl FooIndices { + /// Creates a new copy of `FooIndices` bindings which can then + /// be used to instantiate into a particular store. + /// + /// This method may fail if the component does not have the + /// required exports. + pub fn new( + component: &wasmtime::component::Component, + ) -> wasmtime::Result { + let _component = component; + let f = _component + .export_index(None, "f") + .ok_or_else(|| anyhow::anyhow!("no function export `f` found"))? + .1; + Ok(FooIndices { f }) + } + /// Creates a new instance of [`FooIndices`] from an + /// instantiated component. + /// + /// This method of creating a [`Foo`] will perform string + /// lookups for all exports when this method is called. This + /// will only succeed if the provided instance matches the + /// requirements of [`Foo`]. + pub fn new_instance( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let f = _instance + .get_export(&mut store, None, "f") + .ok_or_else(|| anyhow::anyhow!("no function export `f` found"))?; + Ok(FooIndices { f }) + } + /// Uses the indices stored in `self` to load an instance + /// of [`Foo`] from the instance provided. + /// + /// Note that at this time this method will additionally + /// perform type-checks of all exports. + pub fn load( + &self, + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let _instance = instance; + let f = *_instance + .get_typed_func::<(), ((T, U, R),)>(&mut store, &self.f)? + .func(); + Ok(Foo { f }) + } + } + impl Foo { + /// Convenience wrapper around [`FooPre::new`] and + /// [`FooPre::instantiate_async`]. + pub async fn instantiate_async<_T>( + mut store: impl wasmtime::AsContextMut, + component: &wasmtime::component::Component, + linker: &wasmtime::component::Linker<_T>, + ) -> wasmtime::Result + where + _T: Send + 'static, + { + let pre = linker.instantiate_pre(component)?; + FooPre::new(pre)?.instantiate_async(store).await + } + /// Convenience wrapper around [`FooIndices::new_instance`] and + /// [`FooIndices::load`]. + pub fn new( + mut store: impl wasmtime::AsContextMut, + instance: &wasmtime::component::Instance, + ) -> wasmtime::Result { + let indices = FooIndices::new_instance(&mut store, instance)?; + indices.load(store, instance) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + T: Send + foo::foo::i::Host + 'static, + U: Send + foo::foo::i::Host, + { + foo::foo::i::add_to_linker(linker, get)?; + Ok(()) + } + pub async fn call_f( + &self, + mut store: S, + ) -> wasmtime::Result> + where + ::Data: Send + 'static, + { + let callee = unsafe { + wasmtime::component::TypedFunc::<(), ((T, U, R),)>::new_unchecked(self.f) + }; + let promise = callee.call_concurrent(store.as_context_mut(), ()).await?; + Ok(promise.map(|(v,)| v)) + } + } +}; +pub mod foo { + pub mod foo { + #[allow(clippy::all)] + pub mod i { + #[allow(unused_imports)] + use wasmtime::component::__internal::{anyhow, Box}; + pub type T = u16; + const _: () = { + assert!(2 == < T as wasmtime::component::ComponentType >::SIZE32); + assert!(2 == < T as wasmtime::component::ComponentType >::ALIGN32); + }; + pub trait Host {} + pub trait GetHost< + T, + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + type Host: Host + Send; + } + impl GetHost for F + where + F: Fn(T) -> O + Send + Sync + Copy + 'static, + O: Host + Send, + { + type Host = O; + } + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( + linker: &mut wasmtime::component::Linker, + host_getter: G, + ) -> wasmtime::Result<()> + where + T: Send + 'static, + { + let mut inst = linker.instance("foo:foo/i")?; + Ok(()) + } + pub fn add_to_linker( + linker: &mut wasmtime::component::Linker, + get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, + ) -> wasmtime::Result<()> + where + U: Host + Send, + T: Send + 'static, + { + add_to_linker_get_host(linker, get) + } + impl<_T: Host + ?Sized> Host for &mut _T {} + } + } +} diff --git a/crates/component-macro/tests/expanded/worlds-with-types_tracing_async.rs b/crates/component-macro/tests/expanded/worlds-with-types_tracing_async.rs index 6970a67b8721..3ebb6cb3280e 100644 --- a/crates/component-macro/tests/expanded/worlds-with-types_tracing_async.rs +++ b/crates/component-macro/tests/expanded/worlds-with-types_tracing_async.rs @@ -250,19 +250,23 @@ pub mod foo { pub trait Host: Send {} pub trait GetHost< T, - >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { + D, + >: Fn(T) -> >::Host + Send + Sync + Copy + 'static { type Host: Host + Send; } - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, O: Host + Send, { type Host = O; } - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host< + T, + G: for<'a> GetHost<&'a mut T, T, Host: Host + Send>, + >( linker: &mut wasmtime::component::Linker, - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> wasmtime::Result<()> where T: Send, diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index 2e3779779aff..2a3d1bb96c37 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -62,6 +62,7 @@ semver = { workspace = true, optional = true } smallvec = { workspace = true, optional = true } hashbrown = { workspace = true, features = ["default-hasher"] } bitflags = { workspace = true } +futures = { workspace = true, features = ["alloc"], optional = true } [target.'cfg(target_os = "windows")'.dependencies.windows-sys] workspace = true @@ -371,3 +372,13 @@ custom-native-signals = [] # performance hit, even when not profiling, so it's disabled by default at # compile time. profile-pulley = ['pulley', 'profiling', 'pulley-interpreter/profile'] + +# Enables support for the Component Model Async ABI, along with `future`, +# `stream`, and `error-context` types. +component-model-async = [ + "async", + "component-model", + "std", + "wasmtime-component-macro?/component-model-async", + "dep:futures" +] diff --git a/crates/wasmtime/src/runtime/component/concurrent.rs b/crates/wasmtime/src/runtime/component/concurrent.rs new file mode 100644 index 000000000000..92f2b37d5186 --- /dev/null +++ b/crates/wasmtime/src/runtime/component/concurrent.rs @@ -0,0 +1,74 @@ +use { + crate::AsContextMut, + anyhow::Result, + futures::{stream::FuturesUnordered, FutureExt}, + std::{boxed::Box, future::Future, pin::Pin}, +}; + +pub use futures_and_streams::{ErrorContext, FutureReader, StreamReader}; + +mod futures_and_streams; + +/// Represents the result of a concurrent operation. +/// +/// This is similar to a [`std::future::Future`] except that it represents an +/// operation which requires exclusive access to a store in order to make +/// progress -- without monopolizing that store for the lifetime of the +/// operation. +pub struct Promise(Pin + Send + Sync + 'static>>); + +impl Promise { + /// Map the result of this `Promise` from one value to another. + pub fn map(self, fun: impl FnOnce(T) -> U + Send + Sync + 'static) -> Promise { + Promise(Box::pin(self.0.map(fun))) + } + + /// Convert this `Promise` to a future which may be `await`ed for its + /// result. + /// + /// The returned future will require exclusive use of the store until it + /// completes. If you need to await more than one `Promise` concurrently, + /// use [`PromisesUnordered`]. + pub async fn get(self, store: impl AsContextMut) -> Result { + _ = store; + todo!() + } + + /// Convert this `Promise` to a future which may be `await`ed for its + /// result. + /// + /// Unlike [`Self::get`], this does _not_ take a store parameter, meaning + /// the returned future will not make progress until and unless the event + /// loop for the store it came from is polled. Thus, this method should + /// only be used from within host functions and not from top-level embedder + /// code. + pub fn into_future(self) -> Pin + Send + Sync + 'static>> { + self.0 + } +} + +/// Represents a collection of zero or more concurrent operations. +/// +/// Similar to [`futures::stream::FuturesUnordered`], this type supports +/// `await`ing more than one [`Promise`]s concurrently. +pub struct PromisesUnordered( + FuturesUnordered + Send + Sync + 'static>>>, +); + +impl PromisesUnordered { + /// Create a new `PromisesUnordered` with no entries. + pub fn new() -> Self { + Self(FuturesUnordered::new()) + } + + /// Add the specified [`Promise`] to this collection. + pub fn push(&mut self, promise: Promise) { + self.0.push(promise.0) + } + + /// Get the next result from this collection, if any. + pub async fn next(&mut self, store: impl AsContextMut) -> Result> { + _ = store; + todo!() + } +} diff --git a/crates/wasmtime/src/runtime/component/concurrent/futures_and_streams.rs b/crates/wasmtime/src/runtime/component/concurrent/futures_and_streams.rs new file mode 100644 index 000000000000..af407ddc6d4e --- /dev/null +++ b/crates/wasmtime/src/runtime/component/concurrent/futures_and_streams.rs @@ -0,0 +1,14 @@ +use std::marker::PhantomData; + +/// Represents the readable end of a Component Model `future`. +pub struct FutureReader { + _phantom: PhantomData, +} + +/// Represents the readable end of a Component Model `stream`. +pub struct StreamReader { + _phantom: PhantomData, +} + +/// Represents a Component Model `error-context`. +pub struct ErrorContext {} diff --git a/crates/wasmtime/src/runtime/component/func/typed.rs b/crates/wasmtime/src/runtime/component/func/typed.rs index ecd38faad558..08ddd445ab7a 100644 --- a/crates/wasmtime/src/runtime/component/func/typed.rs +++ b/crates/wasmtime/src/runtime/component/func/typed.rs @@ -17,6 +17,9 @@ use wasmtime_environ::component::{ MAX_FLAT_RESULTS, }; +#[cfg(feature = "component-model-async")] +use crate::component::concurrent::Promise; + /// A statically-typed version of [`Func`] which takes `Params` as input and /// returns `Return`. /// @@ -190,6 +193,31 @@ where .await? } + /// Start concurrent call to this function. + /// + /// Unlike [`Self::call`] and [`Self::call_async`] (both of which require + /// exclusive access to the store until the completion of the call), calls + /// made using this method may run concurrently with other calls to the same + /// instance. + #[cfg(feature = "component-model-async")] + pub async fn call_concurrent( + self, + mut store: impl AsContextMut, + params: Params, + ) -> Result> + where + Params: Send + Sync + 'static, + Return: Send + Sync + 'static, + { + let store = store.as_context_mut(); + assert!( + store.0.async_support(), + "cannot use `call_concurrent` when async support is not enabled on the config" + ); + _ = params; + todo!() + } + fn call_impl(&self, mut store: impl AsContextMut, params: Params) -> Result { let store = &mut store.as_context_mut(); // Note that this is in theory simpler than it might read at this time. diff --git a/crates/wasmtime/src/runtime/component/linker.rs b/crates/wasmtime/src/runtime/component/linker.rs index 31a3d5254884..1a0cd4da4ae7 100644 --- a/crates/wasmtime/src/runtime/component/linker.rs +++ b/crates/wasmtime/src/runtime/component/linker.rs @@ -439,6 +439,41 @@ impl LinkerInstance<'_, T> { self.func_wrap(name, ff) } + /// Defines a new host-provided async function into this [`LinkerInstance`]. + /// + /// This allows the caller to register host functions with the + /// LinkerInstance such that multiple calls to such functions can run + /// concurrently. This isn't possible with the existing func_wrap_async + /// method because it takes a function which returns a future that owns a + /// unique reference to the Store, meaning the Store can't be used for + /// anything else until the future resolves. + /// + /// Ideally, we'd have a way to thread a `StoreContextMut` through an + /// arbitrary `Future` such that it has access to the `Store` only while + /// being polled (i.e. between, but not across, await points). However, + /// there's currently no way to express that in async Rust, so we make do + /// with a more awkward scheme: each function registered using + /// `func_wrap_concurrent` gets access to the `Store` twice: once before + /// doing any concurrent operations (i.e. before awaiting) and once + /// afterward. This allows multiple calls to proceed concurrently without + /// any one of them monopolizing the store. + #[cfg(feature = "component-model-async")] + pub fn func_wrap_concurrent(&mut self, name: &str, f: F) -> Result<()> + where + N: FnOnce(StoreContextMut) -> Result + Send + Sync + 'static, + FN: Future + Send + Sync + 'static, + F: Fn(StoreContextMut, Params) -> FN + Send + Sync + 'static, + Params: ComponentNamedList + Lift + 'static, + Return: ComponentNamedList + Lower + Send + Sync + 'static, + { + assert!( + self.engine.config().async_support, + "cannot use `func_wrap_concurrent` without enabling async support in the config" + ); + _ = (name, f); + todo!() + } + /// Define a new host-provided function using dynamically typed values. /// /// The `name` provided is the name of the function to define and the diff --git a/crates/wasmtime/src/runtime/component/mod.rs b/crates/wasmtime/src/runtime/component/mod.rs index 5c347102903a..1dd845522c6c 100644 --- a/crates/wasmtime/src/runtime/component/mod.rs +++ b/crates/wasmtime/src/runtime/component/mod.rs @@ -101,6 +101,8 @@ #![allow(rustdoc::redundant_explicit_links)] mod component; +#[cfg(feature = "component-model-async")] +pub(crate) mod concurrent; mod func; mod instance; mod linker; @@ -112,6 +114,8 @@ mod store; pub mod types; mod values; pub use self::component::{Component, ComponentExportIndex}; +#[cfg(feature = "component-model-async")] +pub use self::concurrent::{ErrorContext, FutureReader, Promise, PromisesUnordered, StreamReader}; pub use self::func::{ ComponentNamedList, ComponentType, Func, Lift, Lower, TypedFunc, WasmList, WasmStr, }; diff --git a/crates/wit-bindgen/Cargo.toml b/crates/wit-bindgen/Cargo.toml index 90e8ea3e9959..9e958081ce96 100644 --- a/crates/wit-bindgen/Cargo.toml +++ b/crates/wit-bindgen/Cargo.toml @@ -20,3 +20,4 @@ indexmap = { workspace = true } [features] std = [] +component-model-async = ['std'] diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index 810565acf699..dce66a1ac2cd 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -59,10 +59,10 @@ struct Wasmtime { opts: Opts, /// A list of all interfaces which were imported by this world. /// - /// The second value here is the contents of the module that this interface - /// generated. The third value is the name of the interface as also present - /// in `self.interface_names`. - import_interfaces: Vec<(InterfaceId, String, InterfaceName)>, + /// The first two values identify the interface; the third is the contents of the + /// module that this interface generated. The fourth value is the name of the + /// interface as also present in `self.interface_names`. + import_interfaces: Vec<(WorldKey, InterfaceId, String, InterfaceName)>, import_functions: Vec, exports: Exports, types: Types, @@ -134,6 +134,21 @@ pub struct Opts { /// Whether or not to use async rust functions and traits. pub async_: AsyncConfig, + /// Whether or not to use `func_wrap_concurrent` when generating code for + /// async imports. + /// + /// Unlike `func_wrap_async`, `func_wrap_concurrent` allows host functions + /// to suspend without monopolizing the `Store`, meaning other guest tasks + /// can make progress concurrently. + pub concurrent_imports: bool, + + /// Whether or not to use `call_concurrent` when generating code for + /// async exports. + /// + /// Unlike `call_async`, `call_concurrent` allows the caller to make + /// multiple concurrent calls on the same component instance. + pub concurrent_exports: bool, + /// A list of "trappable errors" which are used to replace the `E` in /// `result` found in WIT. pub trappable_error_type: Vec, @@ -175,6 +190,15 @@ pub struct Opts { /// Path to the `wasmtime` crate if it's not the default path. pub wasmtime_crate: Option, + + /// If true, write the generated bindings to a file for better error + /// messages from `rustc`. + /// + /// This can also be toggled via the `WASMTIME_DEBUG_BINDGEN` environment + /// variable, but that will affect _all_ `bindgen!` macro invocations (and + /// can sometimes lead to one invocation ovewriting another in unpredictable + /// ways), whereas this option lets you specify it on a case-by-case basis. + pub debug: bool, } #[derive(Debug, Clone)] @@ -213,28 +237,10 @@ pub enum AsyncConfig { OnlyImports(HashSet), } -impl AsyncConfig { - pub fn is_import_async(&self, f: &str) -> bool { - match self { - AsyncConfig::None => false, - AsyncConfig::All => true, - AsyncConfig::AllExceptImports(set) => !set.contains(f), - AsyncConfig::OnlyImports(set) => set.contains(f), - } - } - - pub fn is_drop_async(&self, r: &str) -> bool { - self.is_import_async(&format!("[drop]{r}")) - } - - pub fn maybe_async(&self) -> bool { - match self { - AsyncConfig::None => false, - AsyncConfig::All | AsyncConfig::AllExceptImports(_) | AsyncConfig::OnlyImports(_) => { - true - } - } - } +pub enum CallStyle { + Sync, + Async, + Concurrent, } #[derive(Default, Debug, Clone)] @@ -260,6 +266,22 @@ impl TrappableImports { impl Opts { pub fn generate(&self, resolve: &Resolve, world: WorldId) -> anyhow::Result { + // TODO: Should we refine this test to inspect only types reachable from + // the specified world? + if !cfg!(feature = "component-model-async") + && resolve.types.iter().any(|(_, ty)| { + matches!( + ty.kind, + TypeDefKind::Future(_) | TypeDefKind::Stream(_) | TypeDefKind::ErrorContext + ) + }) + { + anyhow::bail!( + "must enable `component-model-async` feature when using WIT files \ + containing future, stream, or error types" + ); + } + let mut r = Wasmtime::default(); r.sizes.fill(resolve); r.opts = self.clone(); @@ -268,7 +290,41 @@ impl Opts { } fn is_store_data_send(&self) -> bool { - self.async_.maybe_async() || self.require_store_data_send + matches!(self.call_style(), CallStyle::Async | CallStyle::Concurrent) + || self.require_store_data_send + } + + pub fn import_call_style(&self, qualifier: Option<&str>, f: &str) -> CallStyle { + let matched = |names: &HashSet| { + names.contains(f) + || qualifier + .map(|v| names.contains(&format!("{v}#{f}"))) + .unwrap_or(false) + }; + + match &self.async_ { + AsyncConfig::AllExceptImports(names) if matched(names) => CallStyle::Sync, + AsyncConfig::OnlyImports(names) if !matched(names) => CallStyle::Sync, + _ => self.call_style(), + } + } + + pub fn drop_call_style(&self, qualifier: Option<&str>, r: &str) -> CallStyle { + self.import_call_style(qualifier, &format!("[drop]{r}")) + } + + pub fn call_style(&self) -> CallStyle { + match &self.async_ { + AsyncConfig::None => CallStyle::Sync, + + AsyncConfig::All | AsyncConfig::AllExceptImports(_) | AsyncConfig::OnlyImports(_) => { + if self.concurrent_imports { + CallStyle::Concurrent + } else { + CallStyle::Async + } + } + } } } @@ -455,7 +511,7 @@ impl Wasmtime { // resource-related functions get their trait signatures // during `type_resource`. let sig = if let FunctionKind::Freestanding = func.kind { - generator.generate_function_trait_sig(func); + generator.generate_function_trait_sig(func, "Data"); Some(mem::take(&mut generator.src).into()) } else { None @@ -474,14 +530,14 @@ impl Wasmtime { .interface_last_seen_as_import .insert(*id, true); generator.current_interface = Some((*id, name, false)); - let snake = match name { + let snake = to_rust_ident(&match name { WorldKey::Name(s) => s.to_snake_case(), WorldKey::Interface(id) => resolve.interfaces[*id] .name .as_ref() .unwrap() .to_snake_case(), - }; + }); let module = if generator .generator .name_interface(resolve, *id, name, false) @@ -529,8 +585,12 @@ impl Wasmtime { " ) }; - self.import_interfaces - .push((*id, module, self.interface_names[id].clone())); + self.import_interfaces.push(( + name.clone(), + *id, + module, + self.interface_names[id].clone(), + )); let interface_path = self.import_interface_path(id); self.interface_link_options[id] @@ -815,10 +875,10 @@ fn _new( let wt = self.wasmtime_path(); let world_name = &resolve.worlds[world].name; let camel = to_rust_upper_camel_case(&world_name); - let (async_, async__, where_clause, await_) = if self.opts.async_.maybe_async() { - ("async", "_async", "where _T: Send", ".await") - } else { - ("", "", "", "") + let (async_, async__, where_clause, await_) = match self.opts.call_style() { + CallStyle::Async => ("async", "_async", "where _T: Send", ".await"), + CallStyle::Concurrent => ("async", "_async", "where _T: Send + 'static", ".await"), + CallStyle::Sync => ("", "", "", ""), }; uwriteln!( self.src, @@ -1099,7 +1159,12 @@ impl<_T> {camel}Pre<_T> {{ } let imports = mem::take(&mut self.import_interfaces); - self.emit_modules(imports); + self.emit_modules( + imports + .into_iter() + .map(|(_, id, module, path)| (id, module, path)) + .collect(), + ); let exports = mem::take(&mut self.exports.modules); self.emit_modules(exports); @@ -1366,7 +1431,7 @@ impl Wasmtime { let wt = self.wasmtime_path(); let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name); - if self.opts.async_.maybe_async() { + if let CallStyle::Async = self.opts.call_style() { uwriteln!( self.src, "#[{wt}::component::__internal::trait_variant_make(::core::marker::Send)]" @@ -1374,7 +1439,7 @@ impl Wasmtime { } uwrite!(self.src, "pub trait {world_camel}Imports"); let mut supertraits = vec![]; - if self.opts.async_.maybe_async() { + if let CallStyle::Async = self.opts.call_style() { supertraits.push("Send".to_string()); } for (_, name) in get_world_resources(resolve, world) { @@ -1384,6 +1449,19 @@ impl Wasmtime { uwrite!(self.src, ": {}", supertraits.join(" + ")); } uwriteln!(self.src, " {{"); + + let has_concurrent_function = self.import_functions.iter().any(|func| { + matches!(func.func.kind, FunctionKind::Freestanding) + && matches!( + self.opts.import_call_style(None, &func.func.name), + CallStyle::Concurrent + ) + }); + + if has_concurrent_function { + self.src.push_str("type Data;\n"); + } + for f in self.import_functions.iter() { if let Some(sig) = &f.sig { self.src.push_str(sig); @@ -1392,23 +1470,31 @@ impl Wasmtime { } uwriteln!(self.src, "}}"); + let get_host_bounds = if let CallStyle::Concurrent = self.opts.call_style() { + let constraints = world_imports_concurrent_constraints(resolve, world, &self.opts); + + format!("{world_camel}Imports{}", constraints("D")) + } else { + format!("{world_camel}Imports") + }; + uwriteln!( self.src, " - pub trait {world_camel}ImportsGetHost: - Fn(T) -> >::Host + pub trait {world_camel}ImportsGetHost: + Fn(T) -> >::Host + Send + Sync + Copy + 'static {{ - type Host: {world_camel}Imports; + type Host: {get_host_bounds}; }} - impl {world_camel}ImportsGetHost for F + impl {world_camel}ImportsGetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, - O: {world_camel}Imports + O: {get_host_bounds}, {{ type Host = O; }} @@ -1416,30 +1502,54 @@ impl Wasmtime { ); // Generate impl WorldImports for &mut WorldImports - let maybe_send = if self.opts.async_.maybe_async() { + let maybe_send = if let CallStyle::Async = self.opts.call_style() { "+ Send" } else { "" }; if !self.opts.skip_mut_forwarding_impls { + let maybe_maybe_sized = if let CallStyle::Concurrent = self.opts.call_style() { + "" + } else { + "+ ?Sized" + }; uwriteln!( self.src, - "impl<_T: {world_camel}Imports + ?Sized {maybe_send}> {world_camel}Imports for &mut _T {{" + "impl<_T: {world_camel}Imports {maybe_maybe_sized} {maybe_send}> {world_camel}Imports for &mut _T {{" ); + let has_concurrent_function = self.import_functions.iter().any(|f| { + matches!( + self.opts.import_call_style(None, &f.func.name), + CallStyle::Concurrent + ) + }); + + if has_concurrent_function { + self.src.push_str("type Data = _T::Data;\n"); + } // Forward each method call to &mut T for f in self.import_functions.iter() { if let Some(sig) = &f.sig { self.src.push_str(sig); - uwrite!( - self.src, - "{{ {world_camel}Imports::{}(*self,", - rust_function_name(&f.func) - ); + let call_style = self.opts.import_call_style(None, &f.func.name); + if let CallStyle::Concurrent = &call_style { + uwrite!( + self.src, + "{{ <_T as {world_camel}Imports>::{}(store,", + rust_function_name(&f.func) + ); + } else { + uwrite!( + self.src, + "{{ {world_camel}Imports::{}(*self,", + rust_function_name(&f.func) + ); + } for (name, _) in f.func.params.iter() { uwrite!(self.src, "{},", to_rust_ident(name)); } uwrite!(self.src, ")"); - if self.opts.async_.is_import_async(&f.func.name) { + if let CallStyle::Async = &call_style { uwrite!(self.src, ".await"); } uwriteln!(self.src, "}}"); @@ -1452,7 +1562,7 @@ impl Wasmtime { fn import_interface_paths(&self) -> Vec<(InterfaceId, String)> { self.import_interfaces .iter() - .map(|(id, _, name)| { + .map(|(_, id, _, name)| { let path = match name { InterfaceName::Path(path) => path.join("::"), InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(), @@ -1479,7 +1589,7 @@ impl Wasmtime { let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name); traits.push(format!("{world_camel}Imports")); } - if self.opts.async_.maybe_async() { + if let CallStyle::Async = self.opts.call_style() { traits.push("Send".to_string()); } traits @@ -1498,20 +1608,36 @@ impl Wasmtime { }; let camel = to_rust_upper_camel_case(&resolve.worlds[world].name); + let data_bounds = if self.opts.is_store_data_send() { - "T: Send," + if let CallStyle::Concurrent = self.opts.call_style() { + "T: Send + 'static," + } else { + "T: Send," + } } else { "" }; let wt = self.wasmtime_path(); if has_world_imports_trait { + let host_bounds = if let CallStyle::Concurrent = self.opts.call_style() { + let constraints = world_imports_concurrent_constraints(resolve, world, &self.opts); + + format!("{camel}Imports{}", constraints("T")) + } else { + format!("{camel}Imports") + }; + uwrite!( self.src, " - pub fn add_to_linker_imports_get_host( + pub fn add_to_linker_imports_get_host< + T, + G: for<'a> {camel}ImportsGetHost<&'a mut T, T, Host: {host_bounds}> + >( linker: &mut {wt}::component::Linker, {options_param} - host_getter: impl for<'a> {camel}ImportsGetHost<&'a mut T>, + host_getter: G, ) -> {wt}::Result<()> where {data_bounds} {{ @@ -1521,6 +1647,7 @@ impl Wasmtime { let gate = FeatureGate::open(&mut self.src, &resolve.worlds[world].stability); for (ty, name) in get_world_resources(resolve, world) { Self::generate_add_resource_to_linker( + None, &mut self.src, &self.opts, &wt, @@ -1537,7 +1664,52 @@ impl Wasmtime { uwriteln!(self.src, "Ok(())\n}}"); } - let host_bounds = format!("U: {}", self.world_host_traits(resolve, world).join(" + ")); + let (host_bounds, data_bounds) = if let CallStyle::Concurrent = self.opts.call_style() { + let bounds = self + .import_interfaces + .iter() + .map(|(key, id, _, name)| { + ( + key, + id, + match name { + InterfaceName::Path(path) => path.join("::"), + InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(), + }, + ) + }) + .map(|(key, id, path)| { + format!( + " + {path}::Host{}", + concurrent_constraints( + resolve, + &self.opts, + Some(&resolve.name_world_key(key)), + *id + )("T") + ) + }) + .chain(if self.has_world_imports_trait(resolve, world) { + let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name); + let constraints = + world_imports_concurrent_constraints(resolve, world, &self.opts); + Some(format!(" + {world_camel}Imports{}", constraints("T"))) + } else { + None + }) + .collect::>() + .concat(); + + ( + format!("U: Send{bounds}"), + format!("T: Send{bounds} + 'static,"), + ) + } else { + ( + format!("U: {}", self.world_host_traits(resolve, world).join(" + ")), + data_bounds.to_string(), + ) + }; if !self.opts.skip_mut_forwarding_impls { uwriteln!( @@ -1593,6 +1765,7 @@ impl Wasmtime { } fn generate_add_resource_to_linker( + qualifier: Option<&str>, src: &mut Source, opts: &Opts, wt: &str, @@ -1602,7 +1775,7 @@ impl Wasmtime { ) { let gate = FeatureGate::open(src, stability); let camel = name.to_upper_camel_case(); - if opts.async_.is_drop_async(name) { + if let CallStyle::Async = opts.drop_call_style(qualifier, name) { uwriteln!( src, "{inst}.resource_async( @@ -1673,9 +1846,9 @@ impl<'a> InterfaceGenerator<'a> { TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs), TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs), TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs), - TypeDefKind::Future(_) => todo!("generate for future"), - TypeDefKind::Stream(_) => todo!("generate for stream"), - TypeDefKind::ErrorContext => todo!("generate for error-context"), + TypeDefKind::Future(t) => self.type_future(id, name, t.as_ref(), &ty.docs), + TypeDefKind::Stream(t) => self.type_stream(id, name, t.as_ref(), &ty.docs), + TypeDefKind::ErrorContext => self.type_error_context(id, name, &ty.docs), TypeDefKind::Handle(handle) => self.type_handle(id, name, handle, &ty.docs), TypeDefKind::Resource => self.type_resource(id, name, ty, &ty.docs), TypeDefKind::Unknown => unreachable!(), @@ -1722,13 +1895,14 @@ impl<'a> InterfaceGenerator<'a> { } // Generate resource trait - if self.generator.opts.async_.maybe_async() { + if let CallStyle::Async = self.generator.opts.call_style() { uwriteln!( self.src, "#[{wt}::component::__internal::trait_variant_make(::core::marker::Send)]" ) } - uwriteln!(self.src, "pub trait Host{camel} {{"); + + uwriteln!(self.src, "pub trait Host{camel}: Sized {{"); let mut functions = match resource.owner { TypeOwner::World(id) => self.resolve.worlds[id] @@ -1755,12 +1929,29 @@ impl<'a> InterfaceGenerator<'a> { | FunctionKind::Constructor(resource) => id == resource, }); + let has_concurrent_function = functions.iter().any(|func| { + matches!( + self.generator + .opts + .import_call_style(self.qualifier().as_deref(), &func.name), + CallStyle::Concurrent + ) + }); + + if has_concurrent_function { + uwriteln!(self.src, "type {camel}Data;"); + } + for func in &functions { - self.generate_function_trait_sig(func); + self.generate_function_trait_sig(func, &format!("{camel}Data")); self.push_str(";\n"); } - if self.generator.opts.async_.is_drop_async(name) { + if let CallStyle::Async = self + .generator + .opts + .drop_call_style(self.qualifier().as_deref(), name) + { uwrite!(self.src, "async "); } uwrite!( @@ -1772,32 +1963,56 @@ impl<'a> InterfaceGenerator<'a> { // Generate impl HostResource for &mut HostResource if !self.generator.opts.skip_mut_forwarding_impls { - let maybe_send = if self.generator.opts.async_.maybe_async() { + let maybe_send = if let CallStyle::Async = self.generator.opts.call_style() { "+ Send" } else { "" }; + let maybe_maybe_sized = if has_concurrent_function { + "" + } else { + "+ ?Sized" + }; uwriteln!( self.src, - "impl <_T: Host{camel} + ?Sized {maybe_send}> Host{camel} for &mut _T {{" + "impl <_T: Host{camel} {maybe_maybe_sized} {maybe_send}> Host{camel} for &mut _T {{" ); + if has_concurrent_function { + uwriteln!(self.src, "type {camel}Data = _T::{camel}Data;"); + } for func in &functions { - self.generate_function_trait_sig(func); - uwrite!( - self.src, - "{{ Host{camel}::{}(*self,", - rust_function_name(func) - ); + let call_style = self + .generator + .opts + .import_call_style(self.qualifier().as_deref(), &func.name); + self.generate_function_trait_sig(func, &format!("{camel}Data")); + if let CallStyle::Concurrent = call_style { + uwrite!( + self.src, + "{{ <_T as Host{camel}>::{}(store,", + rust_function_name(func) + ); + } else { + uwrite!( + self.src, + "{{ Host{camel}::{}(*self,", + rust_function_name(func) + ); + } for (name, _) in func.params.iter() { uwrite!(self.src, "{},", to_rust_ident(name)); } uwrite!(self.src, ")"); - if self.generator.opts.async_.is_import_async(&func.name) { + if let CallStyle::Async = call_style { uwrite!(self.src, ".await"); } uwriteln!(self.src, "}}"); } - if self.generator.opts.async_.is_drop_async(name) { + if let CallStyle::Async = self + .generator + .opts + .drop_call_style(self.qualifier().as_deref(), name) + { uwriteln!(self.src, " async fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()> {{ Host{camel}::drop(*self, rep).await @@ -2100,10 +2315,9 @@ impl<'a> InterfaceGenerator<'a> { self.push_str( "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", ); - self.push_str("write!(f, \"{:?}\", self)"); + self.push_str("write!(f, \"{:?}\", self)\n"); self.push_str("}\n"); self.push_str("}\n"); - self.push_str("\n"); if cfg!(feature = "std") { self.push_str("impl"); @@ -2335,6 +2549,35 @@ impl<'a> InterfaceGenerator<'a> { } } + fn type_stream(&mut self, id: TypeId, name: &str, ty: Option<&Type>, docs: &Docs) { + self.rustdoc(docs); + self.push_str(&format!("pub type {name}")); + self.print_generics(None); + self.push_str(" = "); + self.print_stream(ty); + self.push_str(";\n"); + self.assert_type(id, &name); + } + + fn type_future(&mut self, id: TypeId, name: &str, ty: Option<&Type>, docs: &Docs) { + self.rustdoc(docs); + self.push_str(&format!("pub type {name}")); + self.print_generics(None); + self.push_str(" = "); + self.print_future(ty); + self.push_str(";\n"); + self.assert_type(id, &name); + } + + fn type_error_context(&mut self, id: TypeId, name: &str, docs: &Docs) { + self.rustdoc(docs); + self.push_str(&format!("pub type {name}")); + self.push_str(" = "); + self.print_error_context(); + self.push_str(";\n"); + self.assert_type(id, &name); + } + fn print_result_ty(&mut self, results: &Results, mode: TypeMode) { match results { Results::Named(rs) => match rs.len() { @@ -2355,6 +2598,24 @@ impl<'a> InterfaceGenerator<'a> { } } + fn print_result_ty_tuple(&mut self, results: &Results, mode: TypeMode) { + self.push_str("("); + match results { + Results::Named(rs) if rs.is_empty() => self.push_str(")"), + Results::Named(rs) => { + for (_, ty) in rs { + self.print_ty(ty, mode); + self.push_str(", "); + } + self.push_str(")"); + } + Results::Anon(ty) => { + self.print_ty(ty, mode); + self.push_str(",)"); + } + } + } + fn special_case_trappable_error( &mut self, func: &Function, @@ -2397,7 +2658,7 @@ impl<'a> InterfaceGenerator<'a> { let owner = TypeOwner::Interface(id); let wt = self.generator.wasmtime_path(); - let is_maybe_async = self.generator.opts.async_.maybe_async(); + let is_maybe_async = matches!(self.generator.opts.call_style(), CallStyle::Async); if is_maybe_async { uwriteln!( self.src, @@ -2407,24 +2668,45 @@ impl<'a> InterfaceGenerator<'a> { // Generate the `pub trait` which represents the host functionality for // this import which additionally inherits from all resource traits // for this interface defined by `type_resource`. + uwrite!(self.src, "pub trait Host"); let mut host_supertraits = vec![]; if is_maybe_async { host_supertraits.push("Send".to_string()); } + let mut saw_resources = false; for (_, name) in get_resources(self.resolve, id) { + saw_resources = true; host_supertraits.push(format!("Host{}", name.to_upper_camel_case())); } + if saw_resources { + host_supertraits.push("Sized".to_string()); + } if !host_supertraits.is_empty() { uwrite!(self.src, ": {}", host_supertraits.join(" + ")); } uwriteln!(self.src, " {{"); + + let has_concurrent_function = iface.functions.iter().any(|(_, func)| { + matches!(func.kind, FunctionKind::Freestanding) + && matches!( + self.generator + .opts + .import_call_style(self.qualifier().as_deref(), &func.name), + CallStyle::Concurrent + ) + }); + + if has_concurrent_function { + self.push_str("type Data;\n"); + } + for (_, func) in iface.functions.iter() { match func.kind { FunctionKind::Freestanding => {} _ => continue, } - self.generate_function_trait_sig(func); + self.generate_function_trait_sig(func, "Data"); self.push_str(";\n"); } @@ -2472,13 +2754,33 @@ impl<'a> InterfaceGenerator<'a> { } uwriteln!(self.src, "}}"); - let (data_bounds, mut host_bounds) = if self.generator.opts.is_store_data_send() { - ("T: Send,", "Host + Send".to_string()) - } else { - ("", "Host".to_string()) - }; + let (data_bounds, mut host_bounds, mut get_host_bounds) = + match self.generator.opts.call_style() { + CallStyle::Async => ( + "T: Send,".to_string(), + "Host + Send".to_string(), + "Host + Send".to_string(), + ), + CallStyle::Concurrent => { + let constraints = concurrent_constraints( + self.resolve, + &self.generator.opts, + self.qualifier().as_deref(), + id, + ); + + ( + "T: Send + 'static,".to_string(), + format!("Host{} + Send", constraints("T")), + format!("Host{} + Send", constraints("D")), + ) + } + CallStyle::Sync => (String::new(), "Host".to_string(), "Host".to_string()), + }; + for ty in required_conversion_traits { uwrite!(host_bounds, " + {ty}"); + uwrite!(get_host_bounds, " + {ty}"); } let (options_param, options_arg) = if self.generator.interface_link_options[&id].has_any() { @@ -2490,28 +2792,28 @@ impl<'a> InterfaceGenerator<'a> { uwriteln!( self.src, " - pub trait GetHost: - Fn(T) -> >::Host + pub trait GetHost: + Fn(T) -> >::Host + Send + Sync + Copy + 'static {{ - type Host: {host_bounds}; + type Host: {get_host_bounds}; }} - impl GetHost for F + impl GetHost for F where F: Fn(T) -> O + Send + Sync + Copy + 'static, - O: {host_bounds}, + O: {get_host_bounds}, {{ type Host = O; }} - pub fn add_to_linker_get_host( + pub fn add_to_linker_get_host GetHost<&'a mut T, T, Host: {host_bounds}>>( linker: &mut {wt}::component::Linker, {options_param} - host_getter: impl for<'a> GetHost<&'a mut T>, + host_getter: G, ) -> {wt}::Result<()> where {data_bounds} {{ @@ -2522,6 +2824,7 @@ impl<'a> InterfaceGenerator<'a> { for (ty, name) in get_resources(self.resolve, id) { Wasmtime::generate_add_resource_to_linker( + self.qualifier().as_deref(), &mut self.src, &self.generator.opts, &wt, @@ -2559,23 +2862,46 @@ impl<'a> InterfaceGenerator<'a> { // Generate impl Host for &mut Host let maybe_send = if is_maybe_async { "+ Send" } else { "" }; + let maybe_maybe_sized = if has_concurrent_function { + "" + } else { + "+ ?Sized" + }; + uwriteln!( self.src, - "impl<_T: Host + ?Sized {maybe_send}> Host for &mut _T {{" + "impl<_T: Host {maybe_maybe_sized} {maybe_send}> Host for &mut _T {{" ); + + if has_concurrent_function { + self.push_str("type Data = _T::Data;\n"); + } + // Forward each method call to &mut T for (_, func) in iface.functions.iter() { match func.kind { FunctionKind::Freestanding => {} _ => continue, } - self.generate_function_trait_sig(func); - uwrite!(self.src, "{{ Host::{}(*self,", rust_function_name(func)); + let call_style = self + .generator + .opts + .import_call_style(self.qualifier().as_deref(), &func.name); + self.generate_function_trait_sig(func, "Data"); + if let CallStyle::Concurrent = call_style { + uwrite!( + self.src, + "{{ <_T as Host>::{}(store,", + rust_function_name(func) + ); + } else { + uwrite!(self.src, "{{ Host::{}(*self,", rust_function_name(func)); + } for (name, _) in func.params.iter() { uwrite!(self.src, "{},", to_rust_ident(name)); } uwrite!(self.src, ")"); - if self.generator.opts.async_.is_import_async(&func.name) { + if let CallStyle::Async = call_style { uwrite!(self.src, ".await"); } uwriteln!(self.src, "}}"); @@ -2595,15 +2921,24 @@ impl<'a> InterfaceGenerator<'a> { } } + fn qualifier(&self) -> Option { + self.current_interface + .map(|(_, key, _)| self.resolve.name_world_key(key)) + } + fn generate_add_function_to_linker(&mut self, owner: TypeOwner, func: &Function, linker: &str) { let gate = FeatureGate::open(&mut self.src, &func.stability); uwrite!( self.src, "{linker}.{}(\"{}\", ", - if self.generator.opts.async_.is_import_async(&func.name) { - "func_wrap_async" - } else { - "func_wrap" + match self + .generator + .opts + .import_call_style(self.qualifier().as_deref(), &func.name) + { + CallStyle::Sync => "func_wrap", + CallStyle::Async => "func_wrap_async", + CallStyle::Concurrent => "func_wrap_concurrent", }, func.name ); @@ -2627,16 +2962,20 @@ impl<'a> InterfaceGenerator<'a> { self.src.push_str(") : ("); for (_, ty) in func.params.iter() { - // Lift is required to be impled for this type, so we can't use + // Lift is required to be implied for this type, so we can't use // a borrowed type: self.print_ty(ty, TypeMode::Owned); self.src.push_str(", "); } - self.src.push_str(") |"); - self.src.push_str(" {\n"); + self.src.push_str(")| {\n"); + + let style = self + .generator + .opts + .import_call_style(self.qualifier().as_deref(), &func.name); if self.generator.opts.tracing { - if self.generator.opts.async_.is_import_async(&func.name) { + if let CallStyle::Async = style { self.src.push_str("use tracing::Instrument;\n"); } @@ -2662,7 +3001,7 @@ impl<'a> InterfaceGenerator<'a> { ); } - if self.generator.opts.async_.is_import_async(&func.name) { + if let CallStyle::Async = &style { uwriteln!( self.src, " {wt}::component::__internal::Box::new(async move {{ " @@ -2694,8 +3033,11 @@ impl<'a> InterfaceGenerator<'a> { ); } - self.src - .push_str("let host = &mut host_getter(caller.data_mut());\n"); + self.src.push_str(if let CallStyle::Concurrent = &style { + "let host = caller;\n" + } else { + "let host = &mut host_getter(caller.data_mut());\n" + }); let func_name = rust_function_name(func); let host_trait = match func.kind { FunctionKind::Freestanding => match owner { @@ -2714,15 +3056,33 @@ impl<'a> InterfaceGenerator<'a> { format!("Host{resource}") } }; - uwrite!(self.src, "let r = {host_trait}::{func_name}(host, "); + + if let CallStyle::Concurrent = &style { + uwrite!( + self.src, + "let r = ::{func_name}(host, " + ); + } else { + uwrite!(self.src, "let r = {host_trait}::{func_name}(host, "); + } for (i, _) in func.params.iter().enumerate() { uwrite!(self.src, "arg{},", i); } - if self.generator.opts.async_.is_import_async(&func.name) { - uwrite!(self.src, ").await;\n"); - } else { - uwrite!(self.src, ");\n"); + + self.src.push_str(match &style { + CallStyle::Sync | CallStyle::Concurrent => ");\n", + CallStyle::Async => ").await;\n", + }); + + if let CallStyle::Concurrent = &style { + self.src.push_str( + "Box::pin(async move { + let fun = r.await; + Box::new(move |mut caller: wasmtime::StoreContextMut<'_, T>| { + let r = fun(caller); + ", + ); } if self.generator.opts.tracing { @@ -2764,29 +3124,53 @@ impl<'a> InterfaceGenerator<'a> { uwrite!(self.src, "r\n"); } - if self.generator.opts.async_.is_import_async(&func.name) { - // Need to close Box::new and async block - - if self.generator.opts.tracing { - self.src.push_str("}.instrument(span))\n"); - } else { - self.src.push_str("})\n"); + match &style { + CallStyle::Sync => (), + CallStyle::Async => { + if self.generator.opts.tracing { + self.src.push_str("}.instrument(span))\n"); + } else { + self.src.push_str("})\n"); + } + } + CallStyle::Concurrent => { + let old_source = mem::take(&mut self.src); + self.print_result_ty_tuple(&func.results, TypeMode::Owned); + let result_type = String::from(mem::replace(&mut self.src, old_source)); + let box_fn = format!( + "Box) -> \ + wasmtime::Result<{result_type}> + Send + Sync>" + ); + uwriteln!( + self.src, + " }}) as {box_fn} + }}) as ::std::pin::Pin \ + + Send + Sync + 'static>> + " + ); } } - self.src.push_str("}\n"); } - fn generate_function_trait_sig(&mut self, func: &Function) { + fn generate_function_trait_sig(&mut self, func: &Function, data: &str) { let wt = self.generator.wasmtime_path(); self.rustdoc(&func.docs); - if self.generator.opts.async_.is_import_async(&func.name) { + let style = self + .generator + .opts + .import_call_style(self.qualifier().as_deref(), &func.name); + if let CallStyle::Async = &style { self.push_str("async "); } self.push_str("fn "); self.push_str(&rust_function_name(func)); - self.push_str("(&mut self, "); + self.push_str(&if let CallStyle::Concurrent = &style { + format!("(store: wasmtime::StoreContextMut<'_, Self::{data}>, ") + } else { + "(&mut self, ".to_string() + }); for (name, param) in func.params.iter() { let name = to_rust_ident(name); self.push_str(&name); @@ -2797,6 +3181,10 @@ impl<'a> InterfaceGenerator<'a> { self.push_str(")"); self.push_str(" -> "); + if let CallStyle::Concurrent = &style { + uwrite!(self.src, "impl ::std::future::Future) -> "); + } + if !self.generator.opts.trappable_imports.can_trap(func) { self.print_result_ty(&func.results, TypeMode::Owned); } else if let Some((r, _id, error_typename)) = self.special_case_trappable_error(func) { @@ -2819,6 +3207,10 @@ impl<'a> InterfaceGenerator<'a> { self.print_result_ty(&func.results, TypeMode::Owned); self.push_str(">"); } + + if let CallStyle::Concurrent = &style { + self.push_str(" + Send + Sync + 'static> + Send + Sync + 'static where Self: Sized"); + } } fn extract_typed_function(&mut self, func: &Function) -> (String, String) { @@ -2849,12 +3241,16 @@ impl<'a> InterfaceGenerator<'a> { ) { // Exports must be async if anything could be async, it's just imports // that get to be optionally async/sync. - let is_async = self.generator.opts.async_.maybe_async(); - - let (async_, async__, await_) = if is_async { - ("async", "_async", ".await") - } else { - ("", "", "") + let style = self.generator.opts.call_style(); + let (async_, async__, await_, concurrent) = match &style { + CallStyle::Async | CallStyle::Concurrent => { + if self.generator.opts.concurrent_exports { + ("async", "INVALID", "INVALID", true) + } else { + ("async", "_async", ".await", false) + } + } + CallStyle::Sync => ("", "", "", false), }; self.rustdoc(&func.docs); @@ -2866,23 +3262,37 @@ impl<'a> InterfaceGenerator<'a> { func.item_name().to_snake_case(), ); + let param_mode = if let CallStyle::Concurrent = &style { + TypeMode::Owned + } else { + TypeMode::AllBorrowed("'_") + }; + for (i, param) in func.params.iter().enumerate() { uwrite!(self.src, "arg{}: ", i); - self.print_ty(¶m.1, TypeMode::AllBorrowed("'_")); + self.print_ty(¶m.1, param_mode); self.push_str(","); } uwrite!(self.src, ") -> {wt}::Result<"); + if concurrent { + uwrite!(self.src, "{wt}::component::Promise<"); + } self.print_result_ty(&func.results, TypeMode::Owned); - - if is_async { - uwriteln!(self.src, "> where ::Data: Send {{"); - } else { - self.src.push_str("> {\n"); + if concurrent { + uwrite!(self.src, ">"); } - if self.generator.opts.tracing { - if is_async { + let maybe_static = if concurrent { " + 'static" } else { "" }; + + uwrite!( + self.src, + "> where ::Data: Send{maybe_static} {{\n" + ); + + // TODO: support tracing concurrent calls + if self.generator.opts.tracing && !concurrent { + if let CallStyle::Async = &style { self.src.push_str("use tracing::Instrument;\n"); } @@ -2902,7 +3312,7 @@ impl<'a> InterfaceGenerator<'a> { func.name, )); - if !is_async { + if !matches!(&style, CallStyle::Async) { self.src.push_str( " let _enter = span.enter(); @@ -2914,7 +3324,7 @@ impl<'a> InterfaceGenerator<'a> { self.src.push_str("let callee = unsafe {\n"); uwrite!(self.src, "{wt}::component::TypedFunc::<("); for (_, ty) in func.params.iter() { - self.print_ty(ty, TypeMode::AllBorrowed("'_")); + self.print_ty(ty, param_mode); self.push_str(", "); } self.src.push_str("), ("); @@ -2932,46 +3342,65 @@ impl<'a> InterfaceGenerator<'a> { func_field_name(self.resolve, func), ); self.src.push_str("};\n"); - self.src.push_str("let ("); - for (i, _) in func.results.iter_types().enumerate() { - uwrite!(self.src, "ret{},", i); - } - uwrite!( - self.src, - ") = callee.call{async__}(store.as_context_mut(), (" - ); - for (i, _) in func.params.iter().enumerate() { - uwrite!(self.src, "arg{}, ", i); - } - let instrument = if is_async && self.generator.opts.tracing { - ".instrument(span.clone())" - } else { - "" - }; - uwriteln!(self.src, ")){instrument}{await_}?;"); - - let instrument = if is_async && self.generator.opts.tracing { - ".instrument(span)" - } else { - "" - }; - uwriteln!( - self.src, - "callee.post_return{async__}(store.as_context_mut()){instrument}{await_}?;" - ); + if concurrent { + uwrite!( + self.src, + "let promise = callee.call_concurrent(store.as_context_mut(), (" + ); + for (i, _) in func.params.iter().enumerate() { + uwrite!(self.src, "arg{i}, "); + } + self.src.push_str(")).await?;"); - self.src.push_str("Ok("); - if func.results.iter_types().len() == 1 { - self.src.push_str("ret0"); + if func.results.iter_types().len() == 1 { + self.src.push_str("Ok(promise.map(|(v,)| v))\n"); + } else { + self.src.push_str("Ok(promise)"); + } } else { - self.src.push_str("("); + self.src.push_str("let ("); for (i, _) in func.results.iter_types().enumerate() { uwrite!(self.src, "ret{},", i); } - self.src.push_str(")"); + uwrite!( + self.src, + ") = callee.call{async__}(store.as_context_mut(), (" + ); + for (i, _) in func.params.iter().enumerate() { + uwrite!(self.src, "arg{}, ", i); + } + + let instrument = if matches!(&style, CallStyle::Async) && self.generator.opts.tracing { + ".instrument(span.clone())" + } else { + "" + }; + uwriteln!(self.src, ")){instrument}{await_}?;"); + + let instrument = if matches!(&style, CallStyle::Async) && self.generator.opts.tracing { + ".instrument(span)" + } else { + "" + }; + + uwriteln!( + self.src, + "callee.post_return{async__}(store.as_context_mut()){instrument}{await_}?;" + ); + + self.src.push_str("Ok("); + if func.results.iter_types().len() == 1 { + self.src.push_str("ret0"); + } else { + self.src.push_str("("); + for (i, _) in func.results.iter_types().enumerate() { + uwrite!(self.src, "ret{},", i); + } + self.src.push_str(")"); + } + self.src.push_str(")\n"); } - self.src.push_str(")\n"); // End function body self.src.push_str("}\n"); @@ -3250,10 +3679,12 @@ fn type_contains_lists(ty: Type, resolve: &Resolve) -> bool { Type::Id(id) => match &resolve.types[id].kind { TypeDefKind::Resource | TypeDefKind::Unknown - | TypeDefKind::ErrorContext | TypeDefKind::Flags(_) | TypeDefKind::Handle(_) - | TypeDefKind::Enum(_) => false, + | TypeDefKind::Enum(_) + | TypeDefKind::Stream(_) + | TypeDefKind::Future(_) + | TypeDefKind::ErrorContext => false, TypeDefKind::Option(ty) => type_contains_lists(*ty, resolve), TypeDefKind::Result(Result_ { ok, err }) => { option_type_contains_lists(*ok, resolve) @@ -3272,8 +3703,6 @@ fn type_contains_lists(ty: Type, resolve: &Resolve) -> bool { .iter() .any(|case| option_type_contains_lists(case.ty, resolve)), TypeDefKind::Type(ty) => type_contains_lists(*ty, resolve), - TypeDefKind::Future(_) => todo!(), - TypeDefKind::Stream(_) => todo!(), TypeDefKind::List(_) => true, }, @@ -3365,3 +3794,130 @@ fn get_world_resources<'a>( _ => None, }) } + +fn concurrent_constraints<'a>( + resolve: &'a Resolve, + opts: &Opts, + qualifier: Option<&str>, + id: InterfaceId, +) -> impl Fn(&str) -> String + use<'a> { + let has_concurrent_function = resolve.interfaces[id].functions.iter().any(|(_, func)| { + matches!(func.kind, FunctionKind::Freestanding) + && matches!( + opts.import_call_style(qualifier, &func.name), + CallStyle::Concurrent + ) + }); + + let types = resolve.interfaces[id] + .types + .iter() + .filter_map(|(name, ty)| match resolve.types[*ty].kind { + TypeDefKind::Resource + if resolve.interfaces[id] + .functions + .values() + .any(|func| match func.kind { + FunctionKind::Freestanding => false, + FunctionKind::Method(resource) + | FunctionKind::Static(resource) + | FunctionKind::Constructor(resource) => { + *ty == resource + && matches!( + opts.import_call_style(qualifier, &func.name), + CallStyle::Concurrent + ) + } + }) => + { + Some(format!("{}Data", name.to_upper_camel_case())) + } + _ => None, + }) + .chain(has_concurrent_function.then_some("Data".to_string())) + .collect::>(); + + move |v| { + if types.is_empty() { + String::new() + } else { + format!( + "<{}>", + types + .iter() + .map(|s| format!("{s} = {v}")) + .collect::>() + .join(", ") + ) + } + } +} + +fn world_imports_concurrent_constraints<'a>( + resolve: &'a Resolve, + world: WorldId, + opts: &Opts, +) -> impl Fn(&str) -> String + use<'a> { + let has_concurrent_function = resolve.worlds[world] + .imports + .values() + .any(|item| match item { + WorldItem::Function(func) => { + matches!(func.kind, FunctionKind::Freestanding) + && matches!( + opts.import_call_style(None, &func.name), + CallStyle::Concurrent + ) + } + WorldItem::Interface { .. } | WorldItem::Type(_) => false, + }); + + let types = resolve.worlds[world] + .imports + .iter() + .filter_map(|(name, item)| match (name, item) { + (WorldKey::Name(name), WorldItem::Type(ty)) => match resolve.types[*ty].kind { + TypeDefKind::Resource + if resolve.worlds[world] + .imports + .values() + .any(|item| match item { + WorldItem::Function(func) => match func.kind { + FunctionKind::Freestanding => false, + FunctionKind::Method(resource) + | FunctionKind::Static(resource) + | FunctionKind::Constructor(resource) => { + *ty == resource + && matches!( + opts.import_call_style(None, &func.name), + CallStyle::Concurrent + ) + } + }, + WorldItem::Interface { .. } | WorldItem::Type(_) => false, + }) => + { + Some(format!("{}Data", name.to_upper_camel_case())) + } + _ => None, + }, + _ => None, + }) + .chain(has_concurrent_function.then_some("Data".to_string())) + .collect::>(); + + move |v| { + if types.is_empty() { + String::new() + } else { + format!( + "<{}>", + types + .iter() + .map(|s| format!("{s} = {v}")) + .collect::>() + .join(", ") + ) + } + } +} diff --git a/crates/wit-bindgen/src/rust.rs b/crates/wit-bindgen/src/rust.rs index 7b40523be26d..8efd0b045d38 100644 --- a/crates/wit-bindgen/src/rust.rs +++ b/crates/wit-bindgen/src/rust.rs @@ -115,13 +115,12 @@ pub trait RustGenerator<'a> { | TypeDefKind::Enum(_) | TypeDefKind::Tuple(_) | TypeDefKind::Handle(_) - | TypeDefKind::Resource - | TypeDefKind::ErrorContext => true, + | TypeDefKind::Resource => true, TypeDefKind::Type(Type::Id(t)) => { needs_generics(resolve, &resolve.types[*t].kind) } TypeDefKind::Type(Type::String) => true, - TypeDefKind::Type(_) => false, + TypeDefKind::Type(_) | TypeDefKind::ErrorContext => false, TypeDefKind::Unknown => unreachable!(), } } @@ -166,10 +165,19 @@ pub trait RustGenerator<'a> { TypeDefKind::Enum(_) => { panic!("unsupported anonymous type reference: enum") } - TypeDefKind::Future(_) => todo!(), - TypeDefKind::Stream(_) => todo!(), - TypeDefKind::ErrorContext => todo!(), - + TypeDefKind::Future(ty) => { + self.push_str("wasmtime::component::FutureReader<"); + self.print_optional_ty(ty.as_ref(), TypeMode::Owned); + self.push_str(">"); + } + TypeDefKind::Stream(ty) => { + self.push_str("wasmtime::component::StreamReader<"); + self.print_optional_ty(ty.as_ref(), TypeMode::Owned); + self.push_str(">"); + } + TypeDefKind::ErrorContext => { + self.push_str("wasmtime::component::ErrorContext"); + } TypeDefKind::Handle(handle) => { self.print_handle(handle); } @@ -216,6 +224,25 @@ pub trait RustGenerator<'a> { } } + fn print_stream(&mut self, ty: Option<&Type>) { + let wt = self.wasmtime_path(); + self.push_str(&format!("{wt}::component::StreamReader<")); + self.print_optional_ty(ty, TypeMode::Owned); + self.push_str(">"); + } + + fn print_future(&mut self, ty: Option<&Type>) { + let wt = self.wasmtime_path(); + self.push_str(&format!("{wt}::component::FutureReader<")); + self.print_optional_ty(ty, TypeMode::Owned); + self.push_str(">"); + } + + fn print_error_context(&mut self) { + let wt = self.wasmtime_path(); + self.push_str(&format!("{wt}::component::ErrorContext")); + } + fn print_handle(&mut self, handle: &Handle) { // Handles are either printed as `ResourceAny` for any guest-defined // resource or `Resource` for all host-defined resources. This means diff --git a/crates/wit-bindgen/src/types.rs b/crates/wit-bindgen/src/types.rs index 6cb388d4bd16..63bfc63976ef 100644 --- a/crates/wit-bindgen/src/types.rs +++ b/crates/wit-bindgen/src/types.rs @@ -148,21 +148,18 @@ impl Types { info = self.type_info(resolve, ty); info.has_list = true; } - TypeDefKind::Type(ty) => { - info = self.type_info(resolve, ty); - } - TypeDefKind::Option(ty) => { + TypeDefKind::Type(ty) | TypeDefKind::Option(ty) => { info = self.type_info(resolve, ty); } TypeDefKind::Result(r) => { info = self.optional_type_info(resolve, r.ok.as_ref()); info |= self.optional_type_info(resolve, r.err.as_ref()); } - TypeDefKind::Future(_) => todo!(), - TypeDefKind::Stream(_) => todo!(), - TypeDefKind::ErrorContext => todo!(), + TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => { + info = self.optional_type_info(resolve, ty.as_ref()); + } TypeDefKind::Handle(_) => info.has_handle = true, - TypeDefKind::Resource => {} + TypeDefKind::Resource | TypeDefKind::ErrorContext => {} TypeDefKind::Unknown => unreachable!(), } self.type_info.insert(ty, info); diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 32fb28ea011e..430c2947864c 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -1380,50 +1380,32 @@ user-login = "alexcrichton" user-name = "Alex Crichton" [[publisher.wasm-encoder]] -version = "0.220.0" -when = "2024-11-12" -user-id = 73222 -user-login = "wasmtime-publish" - -[[publisher.wasm-encoder]] -version = "0.223.0" -when = "2025-01-08" -user-id = 73222 -user-login = "wasmtime-publish" - -[[publisher.wasm-metadata]] -version = "0.220.0" -when = "2024-11-12" +version = "0.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasm-metadata]] -version = "0.223.0" -when = "2025-01-08" +version = "0.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasm-wave]] -version = "0.223.0" -when = "2025-01-08" +version = "0.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmparser]] -version = "0.220.0" -when = "2024-11-12" -user-id = 73222 -user-login = "wasmtime-publish" - -[[publisher.wasmparser]] -version = "0.223.0" -when = "2025-01-08" +version = "0.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wasmprinter]] -version = "0.223.0" -when = "2025-01-08" +version = "0.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" @@ -1578,14 +1560,14 @@ user-id = 73222 user-login = "wasmtime-publish" [[publisher.wast]] -version = "223.0.0" -when = "2025-01-08" +version = "224.0.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wat]] -version = "1.223.0" -when = "2025-01-08" +version = "1.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" @@ -1810,14 +1792,14 @@ user-login = "sunfishcode" user-name = "Dan Gohman" [[publisher.wit-bindgen]] -version = "0.37.0" -when = "2025-01-10" +version = "0.38.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wit-bindgen-core]] -version = "0.37.0" -when = "2025-01-10" +version = "0.38.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" @@ -1827,39 +1809,33 @@ when = "2025-01-10" user-id = 73222 user-login = "wasmtime-publish" -[[publisher.wit-bindgen-rust]] -version = "0.37.0" -when = "2025-01-10" +[[publisher.wit-bindgen-rt]] +version = "0.38.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" -[[publisher.wit-bindgen-rust-macro]] -version = "0.37.0" -when = "2025-01-10" +[[publisher.wit-bindgen-rust]] +version = "0.38.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" -[[publisher.wit-component]] -version = "0.220.0" -when = "2024-11-12" +[[publisher.wit-bindgen-rust-macro]] +version = "0.38.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wit-component]] -version = "0.223.0" -when = "2025-01-08" -user-id = 73222 -user-login = "wasmtime-publish" - -[[publisher.wit-parser]] -version = "0.220.0" -when = "2024-11-12" +version = "0.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish" [[publisher.wit-parser]] -version = "0.223.0" -when = "2025-01-08" +version = "0.224.0" +when = "2025-01-22" user-id = 73222 user-login = "wasmtime-publish"