Repository: bytecodealliance/wasmtime
Pull request #9297 (2024-09-24 04:50:23)

ci: use node20 for github release action
Blog post: https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/



Patch:
diff --git a/.github/actions/github-release/action.yml b/.github/actions/github-release/action.yml
index 17c4715b9..6396413cb 100644
--- a/.github/actions/github-release/action.yml
+++ b/.github/actions/github-release/action.yml
@@ -8,5 +8,5 @@ inputs:
     description: ''
     required: true
 runs:
-  using: 'node16'
+  using: 'node20'
   main: 'main.js'
diff --git a/Cargo.toml b/Cargo.toml
index ff1c1e001..ee5cce641 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -437,12 +437,25 @@ gc = ["wasmtime-cli-flags/gc"]
 
 # CLI subcommands for the `wasmtime` executable. See `wasmtime $cmd --help`
 # for more information on each subcommand.
-serve = ["wasi-http", "component-model", "dep:http-body-util", "dep:http"]
+serve = [
+  "wasi-http",
+  "component-model",
+  "dep:http-body-util",
+  "dep:http",
+  "wasmtime-cli-flags/async",
+]
 explore = ["dep:wasmtime-explorer", "dep:tempfile"]
 wast = ["dep:wasmtime-wast"]
 config = ["cache"]
 compile = ["cranelift"]
-run = ["dep:wasmtime-wasi", "wasmtime/runtime", "dep:listenfd", "dep:wasi-common", "dep:tokio"]
+run = [
+  "dep:wasmtime-wasi",
+  "wasmtime/runtime",
+  "dep:listenfd",
+  "dep:wasi-common",
+  "dep:tokio",
+  "wasmtime-cli-flags/async",
+]
 
 [[test]]
 name = "host_segfault"
diff --git a/cranelift/codegen/src/ir/memflags.rs b/cranelift/codegen/src/ir/memflags.rs
index f604a324c..fe34dbe7c 100644
--- a/cranelift/codegen/src/ir/memflags.rs
+++ b/cranelift/codegen/src/ir/memflags.rs
@@ -361,7 +361,7 @@ impl MemFlags {
             0b1001 => Some(TrapCode::UnreachableCodeReached),
             0b1010 => Some(TrapCode::Interrupt),
             0b1011 => Some(TrapCode::NullReference),
-            0b1100 => Some(TrapCode::NullI31Ref),
+            0b1100 => Some(TrapCode::ArrayOutOfBounds),
             // 0b1101 => {} not allocated
             // 0b1110 => {} not allocated
             0b1111 => None,
@@ -390,7 +390,7 @@ impl MemFlags {
             Some(TrapCode::UnreachableCodeReached) => 0b1001,
             Some(TrapCode::Interrupt) => 0b1010,
             Some(TrapCode::NullReference) => 0b1011,
-            Some(TrapCode::NullI31Ref) => 0b1100,
+            Some(TrapCode::ArrayOutOfBounds) => 0b1100,
             None => 0b1111,
 
             Some(TrapCode::User(_)) => panic!("cannot set user trap code in mem flags"),
diff --git a/cranelift/codegen/src/ir/trapcode.rs b/cranelift/codegen/src/ir/trapcode.rs
index e33a65545..9d2508261 100644
--- a/cranelift/codegen/src/ir/trapcode.rs
+++ b/cranelift/codegen/src/ir/trapcode.rs
@@ -27,6 +27,9 @@ pub enum TrapCode {
     /// A `table_addr` instruction detected an out-of-bounds error.
     TableOutOfBounds,
 
+    /// An array access attempted to index beyond its array's bounds.
+    ArrayOutOfBounds,
+
     /// Indirect call to a null table entry.
     IndirectCallToNull,
 
@@ -53,9 +56,6 @@ pub enum TrapCode {
 
     /// A null reference was encountered which was required to be non-null.
     NullReference,
-
-    /// A null `i31ref` was encountered which was required to be non-null.
-    NullI31Ref,
 }
 
 impl TrapCode {
@@ -95,7 +95,7 @@ impl Display for TrapCode {
             Interrupt => "interrupt",
             User(x) => return write!(f, "user{x}"),
             NullReference => "null_reference",
-            NullI31Ref => "null_i31ref",
+            ArrayOutOfBounds => "array_oob",
         };
         f.write_str(identifier)
     }
@@ -119,7 +119,7 @@ impl FromStr for TrapCode {
             "unreachable" => Ok(UnreachableCodeReached),
             "interrupt" => Ok(Interrupt),
             "null_reference" => Ok(NullReference),
-            "null_i31ref" => Ok(NullI31Ref),
+            "array_oob" => Ok(ArrayOutOfBounds),
             _ if s.starts_with("user") => s[4..].parse().map(User).map_err(|_| ()),
             _ => Err(()),
         }
diff --git a/crates/cli-flags/src/lib.rs b/crates/cli-flags/src/lib.rs
index ece1e20bc..c8ff1e2c4 100644
--- a/crates/cli-flags/src/lib.rs
+++ b/crates/cli-flags/src/lib.rs
@@ -202,6 +202,12 @@ wasmtime_option_group! {
         /// Maximum stack size, in bytes, that wasm is allowed to consume before a
         /// stack overflow is reported.
         pub max_wasm_stack: Option<usize>,
+        /// Stack size, in bytes, that will be allocated for async stacks.
+        ///
+        /// Note that this must be larger than `max-wasm-stack` and the
+        /// difference between the two is how much stack the host has to execute
+        /// on.
+        pub async_stack_size: Option<usize>,
         /// Allow unknown exports when running commands.
         pub unknown_exports_allow: Option<bool>,
         /// Allow the main module to import unknown functions, using an
@@ -658,8 +664,23 @@ impl CommonOptions {
             anyhow::bail!("memory protection keys require the pooling allocator");
         }
 
+        match_feature! {
+            ["async" : self.wasm.async_stack_size]
+            size => config.async_stack_size(size),
+            _ => err,
+        }
+
         if let Some(max) = self.wasm.max_wasm_stack {
             config.max_wasm_stack(max);
+
+            // If `-Wasync-stack-size` isn't passed then automatically adjust it
+            // to the wasm stack size provided here too. That prevents the need
+            // to pass both when one can generally be inferred from the other.
+            #[cfg(feature = "async")]
+            if self.wasm.async_stack_size.is_none() {
+                const DEFAULT_HOST_STACK: usize = 512 << 10;
+                config.async_stack_size(max + DEFAULT_HOST_STACK);
+            }
         }
 
         if let Some(enable) = self.wasm.relaxed_simd_deterministic {
diff --git a/crates/component-macro/src/bindgen.rs b/crates/component-macro/src/bindgen.rs
index f17184dd8..d443748b5 100644
--- a/crates/component-macro/src/bindgen.rs
+++ b/crates/component-macro/src/bindgen.rs
@@ -80,7 +80,7 @@ impl Parse for Config {
         let mut opts = Opts::default();
         let mut world = None;
         let mut inline = None;
-        let mut path = None;
+        let mut paths = Vec::new();
         let mut async_configured = false;
         let mut features = Vec::new();
         let mut include_generated_code_from_file = false;
@@ -91,11 +91,8 @@ impl Parse for Config {
             let fields = Punctuated::<Opt, Token![,]>::parse_terminated(&content)?;
             for field in fields.into_pairs() {
                 match field.into_value() {
-                    Opt::Path(s) => {
-                        if path.is_some() {
-                            return Err(Error::new(s.span(), "cannot specify second path"));
-                        }
-                        path = Some(s.value());
+                    Opt::Path(p) => {
+                        paths.extend(p.into_iter().map(|p| p.value()));
                     }
                     Opt::World(s) => {
                         if world.is_some() {
@@ -168,14 +165,13 @@ impl Parse for Config {
         } else {
             world = input.parse::<Option<syn::LitStr>>()?.map(|s| s.value());
             if input.parse::<Option<syn::token::In>>()?.is_some() {
-                path = Some(input.parse::<syn::LitStr>()?.value());
+                paths.push(input.parse::<syn::LitStr>()?.value());
             }
         }
-        let (resolve, pkg, files) = parse_source(&path, &inline, &features)
+        let (resolve, pkgs, files) = parse_source(&paths, &inline, &features)
             .map_err(|err| Error::new(call_site, format!("{err:?}")))?;
 
-        let world = resolve
-            .select_world(pkg, world.as_deref())
+        let world = select_world(&resolve, &pkgs, world.as_deref())
             .map_err(|e| Error::new(call_site, format!("{e:?}")))?;
         Ok(Config {
             opts,
@@ -188,47 +184,89 @@ impl Parse for Config {
 }
 
 fn parse_source(
-    path: &Option<String>,
+    paths: &Vec<String>,
     inline: &Option<String>,
     features: &[String],
-) -> anyhow::Result<(Resolve, PackageId, Vec<PathBuf>)> {
+) -> anyhow::Result<(Resolve, Vec<PackageId>, Vec<PathBuf>)> {
     let mut resolve = Resolve::default();
     resolve.features.extend(features.iter().cloned());
     let mut files = Vec::new();
+    let mut pkgs = Vec::new();
     let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
 
-    let mut parse = |resolve: &mut Resolve, path: &Path| -> anyhow::Result<_> {
-        // Try to normalize the path to make the error message more understandable when
-        // the path is not correct. Fallback to the original path if normalization fails
-        // (probably return an error somewhere else).
-        let normalized_path = match std::fs::canonicalize(path) {
-            Ok(p) => p,
-            Err(_) => path.to_path_buf(),
-        };
-        let (pkg, sources) = resolve.push_path(normalized_path)?;
-        files.extend(sources);
-        Ok(pkg)
+    let parse = |resolve: &mut Resolve,
+                 files: &mut Vec<PathBuf>,
+                 pkgs: &mut Vec<PackageId>,
+                 paths: &[String]|
+     -> anyhow::Result<_> {
+        for path in paths {
+            let p = root.join(path);
+            // Try to normalize the path to make the error message more understandable when
+            // the path is not correct. Fallback to the original path if normalization fails
+            // (probably return an error somewhere else).
+            let normalized_path = match std::fs::canonicalize(&p) {
+                Ok(p) => p,
+                Err(_) => p.to_path_buf(),
+            };
+            let (pkg, sources) = resolve.push_path(normalized_path)?;
+            pkgs.push(pkg);
+            files.extend(sources);
+        }
+        Ok(())
     };
 
-    let path_pkg = if let Some(path) = path {
-        Some(parse(&mut resolve, &root.join(path))?)
-    } else {
-        None
-    };
+    if !paths.is_empty() {
+        parse(&mut resolve, &mut files, &mut pkgs, &paths)?;
+    }
 
-    let inline_pkgs = if let Some(inline) = inline {
-        Some(resolve.push_group(UnresolvedPackageGroup::parse("macro-input", inline)?)?)
-    } else {
-        None
-    };
+    if let Some(inline) = inline {
+        pkgs.push(resolve.push_group(UnresolvedPackageGroup::parse("macro-input", inline)?)?);
+    }
 
-    let pkgs = inline_pkgs
-        .or(path_pkg)
-        .map_or_else(|| parse(&mut resolve, &root.join("wit")), Ok)?;
+    if pkgs.is_empty() {
+        parse(&mut resolve, &mut files, &mut pkgs, &["wit".into()])?;
+    }
 
     Ok((resolve, pkgs, files))
 }
 
+fn select_world(
+    resolve: &Resolve,
+    pkgs: &[PackageId],
+    world: Option<&str>,
+) -> anyhow::Result<WorldId> {
+    if pkgs.len() == 1 {
+        resolve.select_world(pkgs[0], world)
+    } else {
+        assert!(!pkgs.is_empty());
+        match world {
+            Some(name) => {
+                if !name.contains(":") {
+                    anyhow::bail!(
+                        "with multiple packages a fully qualified \
+                         world name must be specified"
+                    )
+                }
+
+                // This will ignore the package argument due to the fully
+                // qualified name being used.
+                resolve.select_world(pkgs[0], world)
+            }
+            None => {
+                let worlds = pkgs
+                    .iter()
+                    .filter_map(|p| resolve.select_world(*p, None).ok())
+                    .collect::<Vec<_>>();
+                match &worlds[..] {
+                    [] => anyhow::bail!("no packages have a world"),
+                    [world] => Ok(*world),
+                    _ => anyhow::bail!("multiple packages have a world, must specify which to use"),
+                }
+            }
+        }
+    }
+}
+
 mod kw {
     syn::custom_keyword!(inline);
     syn::custom_keyword!(path);
@@ -253,7 +291,7 @@ mod kw {
 
 enum Opt {
     World(syn::LitStr),
-    Path(syn::LitStr),
+    Path(Vec<syn::LitStr>),
     Inline(syn::LitStr),
     Tracing(bool),
     VerboseTracing(bool),
@@ -278,7 +316,27 @@ impl Parse for Opt {
         if l.peek(kw::path) {
             input.parse::<kw::path>()?;
             input.parse::<Token![:]>()?;
-            Ok(Opt::Path(input.parse()?))
+
+            let mut paths: Vec<syn::LitStr> = vec![];
+
+            let l = input.lookahead1();
+            if l.peek(syn::LitStr) {
+                paths.push(input.parse()?);
+            } else if l.peek(syn::token::Bracket) {
+                let contents;
+                syn::bracketed!(contents in input);
+                let list = Punctuated::<_, Token![,]>::parse_terminated(&contents)?;
+
+                paths.extend(list.into_iter());
+
+                if input.peek(Token![,]) {
+                    input.parse::<Token![,]>()?;
+                }
+            } else {
+                return Err(l.error());
+            };
+
+            Ok(Opt::Path(paths))
         } else if l.peek(kw::inline) {
             input.parse::<kw::inline>()?;
             input.parse::<Token![:]>()?;
diff --git a/crates/cranelift-shared/src/lib.rs b/crates/cranelift-shared/src/lib.rs
index 408c266e0..1b72ef884 100644
--- a/crates/cranelift-shared/src/lib.rs
+++ b/crates/cranelift-shared/src/lib.rs
@@ -86,7 +86,6 @@ pub fn mach_trap_to_trap(trap: &MachTrap) -> Option<TrapInformation> {
             ir::TrapCode::User(ALWAYS_TRAP_CODE) => Trap::AlwaysTrapAdapter,
             ir::TrapCode::User(CANNOT_ENTER_CODE) => Trap::CannotEnterComponent,
             ir::TrapCode::NullReference => Trap::NullReference,
-            ir::TrapCode::NullI31Ref => Trap::NullI31Ref,
 
             // These do not get converted to wasmtime traps, since they
             // shouldn't ever be hit in theory. Instead of catching and handling
diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs
index 56d88d663..f23927546 100644
--- a/crates/cranelift/src/func_environ.rs
+++ b/crates/cranelift/src/func_environ.rs
@@ -1851,7 +1851,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
         // TODO: If we knew we have a `(ref i31)` here, instead of maybe a `(ref
         // null i31)`, we could omit the `trapz`. But plumbing that type info
         // from `wasmparser` and through to here is a bit funky.
-        self.trapz(builder, i31ref, ir::TrapCode::NullI31Ref);
+        self.trapz(builder, i31ref, ir::TrapCode::NullReference);
         Ok(builder.ins().sshr_imm(i31ref, 1))
     }
 
@@ -1863,7 +1863,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
         // TODO: If we knew we have a `(ref i31)` here, instead of maybe a `(ref
         // null i31)`, we could omit the `trapz`. But plumbing that type info
         // from `wasmparser` and through to here is a bit funky.
-        self.trapz(builder, i31ref, ir::TrapCode::NullI31Ref);
+        self.trapz(builder, i31ref, ir::TrapCode::NullReference);
         Ok(builder.ins().ushr_imm(i31ref, 1))
     }
 
diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs
index cbfcc7a5b..467a994eb 100644
--- a/crates/cranelift/src/lib.rs
+++ b/crates/cranelift/src/lib.rs
@@ -248,7 +248,7 @@ fn clif_trap_to_env_trap(trap: ir::TrapCode) -> Option<Trap> {
         ir::TrapCode::User(ALWAYS_TRAP_CODE) => Trap::AlwaysTrapAdapter,
         ir::TrapCode::User(CANNOT_ENTER_CODE) => Trap::CannotEnterComponent,
         ir::TrapCode::NullReference => Trap::NullReference,
-        ir::TrapCode::NullI31Ref => Trap::NullI31Ref,
+        ir::TrapCode::ArrayOutOfBounds => Trap::ArrayOutOfBounds,
 
         // These do not get converted to wasmtime traps, since they
         // shouldn't ever be hit in theory. Instead of catching and handling
diff --git a/crates/environ/src/trap_encoding.rs b/crates/environ/src/trap_encoding.rs
index 32d9e19e7..9b92336a2 100644
--- a/crates/environ/src/trap_encoding.rs
+++ b/crates/environ/src/trap_encoding.rs
@@ -74,8 +74,8 @@ pub enum Trap {
     /// Call to a null reference.
     NullReference,
 
-    /// Attempt to get the bits of a null `i31ref`.
-    NullI31Ref,
+    /// Attempt to access beyond the bounds of an array.
+    ArrayOutOfBounds,
 
     /// When the `component-model` feature is enabled this trap represents a
     /// scenario where one component tried to call another component but it
@@ -114,7 +114,7 @@ impl Trap {
             OutOfFuel
             AtomicWaitNonSharedMemory
             NullReference
-            NullI31Ref
+            ArrayOutOfBounds
             CannotEnterComponent
         }
 
@@ -142,7 +142,7 @@ impl fmt::Display for Trap {
             OutOfFuel => "all fuel consumed by WebAssembly",
             AtomicWaitNonSharedMemory => "atomic wait on non-shared memory",
             NullReference => "null reference",
-            NullI31Ref => "null i31 reference",
+            ArrayOutOfBounds => "out of bounds array access",
             CannotEnterComponent => "cannot enter component instance",
         };
         write!(f, "wasm trap: {desc}")
diff --git a/docs/stability-tiers.md b/docs/stability-tiers.md
index 7a9a20465..f19b4842a 100644
--- a/docs/stability-tiers.md
+++ b/docs/stability-tiers.md
@@ -71,7 +71,6 @@ For explanations of what each tier means see below.
 | Target               | `s390x-unknown-linux-gnu`  | Continuous fuzzing          |
 | Target               | `x86_64-pc-windows-gnu`    | Clear owner of the target   |
 | Target               | Support for `#![no_std]`   | Support beyond CI checks    |
-| Compiler Backend     | Winch on x86\_64           | Consenus on moving to Tier 1 |
 | WebAssembly Proposal | [`memory64`]               | Unstable wasm proposal      |
 | WebAssembly Proposal | [`function-references`]    | Unstable wasm proposal      |
 
@@ -92,7 +91,8 @@ For explanations of what each tier means see below.
 | Target               | `aarch64-linux-android`           | CI testing, full-time maintainer |
 | Target               | `x86_64-linux-android`            | CI testing, full-time maintainer |
 | Target               | `x86_64-unknown-linux-musl` [^4]  | CI testing, full-time maintainer |
-| Compiler Backend     | Winch on aarch64                  | finished implementation     |
+| Compiler Backend     | Winch on x86\_64                  | WebAssembly proposals (`simd`, `relaxed-simd`, `tail-call`, `reference-types`, `threads`)     |
+| Compiler Backend     | Winch on aarch64                  | Complete implementation     |
 | WebAssembly Proposal | [`gc`]                            | Complete implementation     |
 | WASI Proposal        | [`wasi-nn`]                       | More expansive CI testing   |
 | WASI Proposal        | [`wasi-threads`]                  | More CI, unstable proposal  |
diff --git a/winch/README.md b/winch/README.md
new file mode 100644
index 000000000..1b47d1eb2
--- /dev/null
+++ b/winch/README.md
@@ -0,0 +1,69 @@
+<div align="center">
+  <h1>Winch</h1>
+
+  <h3>WebAssembly Intentionally Non-optimizing Compiler and Host</h3>
+
+  <p>
+    <strong>A WebAssembly baseline compiler</strong>
+  </p>
+
+  <strong>A <a href="https://bytecodealliance.org/">Bytecode Alliance</a> project</strong>
+
+  <p>
+    <a href="https://github.com/bytecodealliance/wasmtime/actions?query=workflow%3ACI"><img src="https://github.com/bytecodealliance/wasmtime/workflows/CI/badge.svg" alt="build status" /></a>
+    <a href="https://bytecodealliance.zulipchat.com/#narrow/stream/417703-winch"><img src="https://img.shields.io/badge/zulip-join_chat-brightgreen.svg" alt="zulip chat" /></a>
+    <img src="https://img.shields.io/badge/rustc-stable+-green.svg" alt="supported rustc stable" />
+    <a href="https://docs.rs/winch-codegen"><img src="https://docs.rs/winch-codegen/badge.svg" alt="Documentation Status" /></a>
+  </p>
+</div>
+
+## About
+
+Winch is a WebAssembly "baseline" or single-pass compiler designed for Wasmtime.
+
+Winch's primary goal is compilation performance, therefore only certain, very
+limited peephole optimations are applied.
+
+For more details on the original motivation and goals, refer to the [Bytecode
+Alliance RFC for Baseline Compilation in Wasmtime.](rfc).
+
+[rfc]: https://github.com/bytecodealliance/rfcs/blob/main/accepted/wasmtime-baseline-compilation.md
+
+## Design principles
+
+* Single pass over Wasm bytecode
+
+* Function as the unit of compilation
+
+* Machine code generation directly from Wasm bytecode – no intermediate
+  representation
+
+* Avoid reinventing machine-code emission – use Cranelift's instruction emitter
+  code to create an assembler library
+
+* Prioritize compilation performance over runtime performance
+
+* Simple to verify by looking. It should be evident which machine instructions
+  are emitted per WebAssembly operator
+
+* Adding and iterating on new (WebAssembly and developer-facing) features should
+  be simpler than doing it in an optimizing tier (Cranelift)
+
+
+## Status
+
+Winch's aim is to support all the backends officially supported by Wasmtime:
+
+* x64\_64
+* arm64
+* riscv64
+* s390x
+
+The x86\_64 backend offers an almost-complete implementation, it currently
+supports all the instructions that are part of WebAssembly's MVP, plus some of
+the [feature extensions](feature-extensions). Refer to the [Tiers of
+Support](tiers-of-support) for more details.
+
+
+[feature-extensions]: https://webassembly.org/features/
+[tiers-of-support]: https://docs.wasmtime.dev/stability-tiers.html


Test patch:
diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs
index 1d0f02118..48334fc5f 100644
--- a/crates/component-macro/tests/codegen.rs
+++ b/crates/component-macro/tests/codegen.rs
@@ -112,6 +112,7 @@ mod with_key_and_resources {
 
 mod trappable_errors_with_versioned_and_unversioned_packages {
     wasmtime::component::bindgen!({
+        world: "foo:foo/nope",
         inline: "
             package foo:foo@0.1.0;
 
@@ -697,3 +698,19 @@ mod trappable_error_type_and_versions {
         });
     }
 }
+
+mod paths {
+    mod multiple_paths {
+        wasmtime::component::bindgen!({
+            world: "test:paths/test",
+            inline: r#"
+            package test:paths;
+            world test {
+                import paths:path1/test;
+                export paths:path2/test;
+            }
+            "#,
+            path: ["tests/codegen/path1", "tests/codegen/path2"],
+        });
+    }
+}
diff --git a/crates/component-macro/tests/codegen/path1/world.wit b/crates/component-macro/tests/codegen/path1/world.wit
new file mode 100644
index 000000000..8a72a8fc8
--- /dev/null
+++ b/crates/component-macro/tests/codegen/path1/world.wit
@@ -0,0 +1,7 @@
+package paths:path1;
+
+interface test {}
+
+world path1 {
+    import test;
+}
diff --git a/crates/component-macro/tests/codegen/path2/world.wit b/crates/component-macro/tests/codegen/path2/world.wit
new file mode 100644
index 000000000..54367a409
--- /dev/null
+++ b/crates/component-macro/tests/codegen/path2/world.wit
@@ -0,0 +1,7 @@
+package paths:path2;
+
+interface test {}
+
+world path2 {
+    import test;
+}
diff --git a/crates/component-macro/tests/expanded/path1.rs b/crates/component-macro/tests/expanded/path1.rs
new file mode 100644
index 000000000..a4ce53636
--- /dev/null
+++ b/crates/component-macro/tests/expanded/path1.rs
@@ -0,0 +1,208 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Path1Indices,
+}
+impl<T> Clone for Path1Pre<T> {
+    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<Self> {
+        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 fn instantiate(
+        &self,
+        mut store: impl wasmtime::AsContextMut<Data = _T>,
+    ) -> wasmtime::Result<Path1> {
+        let mut store = store.as_context_mut();
+        let instance = self.instance_pre.instantiate(&mut store)?;
+        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`] 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`] 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<Self> {
+            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<Self> {
+            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<Path1> {
+            let _instance = instance;
+            Ok(Path1 {})
+        }
+    }
+    impl Path1 {
+        /// Convenience wrapper around [`Path1Pre::new`] and
+        /// [`Path1Pre::instantiate`].
+        pub fn instantiate<_T>(
+            mut store: impl wasmtime::AsContextMut<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Path1> {
+            let pre = linker.instantiate_pre(component)?;
+            Path1Pre::new(pre)?.instantiate(store)
+        }
+        /// Convenience wrapper around [`Path1Indices::new_instance`] and
+        /// [`Path1Indices::load`].
+        pub fn new(
+            mut store: impl wasmtime::AsContextMut,
+            instance: &wasmtime::component::Instance,
+        ) -> wasmtime::Result<Path1> {
+            let indices = Path1Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker<T, U>(
+            linker: &mut wasmtime::component::Linker<T>,
+            get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+        ) -> wasmtime::Result<()>
+        where
+            U: 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;
+            pub trait Host {}
+            pub trait GetHost<
+                T,
+            >: Fn(T) -> <Self as GetHost<T>>::Host + Send + Sync + Copy + 'static {
+                type Host: Host;
+            }
+            impl<F, T, O> GetHost<T> for F
+            where
+                F: Fn(T) -> O + Send + Sync + Copy + 'static,
+                O: Host,
+            {
+                type Host = O;
+            }
+            pub fn add_to_linker_get_host<T>(
+                linker: &mut wasmtime::component::Linker<T>,
+                host_getter: impl for<'a> GetHost<&'a mut T>,
+            ) -> wasmtime::Result<()> {
+                let mut inst = linker.instance("paths:path1/test")?;
+                Ok(())
+            }
+            pub fn add_to_linker<T, U>(
+                linker: &mut wasmtime::component::Linker<T>,
+                get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+            ) -> wasmtime::Result<()>
+            where
+                U: Host,
+            {
+                add_to_linker_get_host(linker, get)
+            }
+            impl<_T: Host + ?Sized> Host for &mut _T {}
+        }
+    }
+}
diff --git a/crates/component-macro/tests/expanded/path1_async.rs b/crates/component-macro/tests/expanded/path1_async.rs
new file mode 100644
index 000000000..45f121cdd
--- /dev/null
+++ b/crates/component-macro/tests/expanded/path1_async.rs
@@ -0,0 +1,221 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Path1Indices,
+}
+impl<T> Clone for Path1Pre<T> {
+    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<Self> {
+        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<Data = _T>,
+    ) -> wasmtime::Result<Path1>
+    where
+        _T: Send,
+    {
+        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<Self> {
+            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<Self> {
+            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<Path1> {
+            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<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Path1>
+        where
+            _T: Send,
+        {
+            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<Path1> {
+            let indices = Path1Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker<T, U>(
+            linker: &mut wasmtime::component::Linker<T>,
+            get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+        ) -> wasmtime::Result<()>
+        where
+            T: Send,
+            U: paths::path1::test::Host + Send,
+        {
+            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;
+            #[wasmtime::component::__internal::async_trait]
+            pub trait Host: Send {}
+            pub trait GetHost<
+                T,
+            >: Fn(T) -> <Self as GetHost<T>>::Host + Send + Sync + Copy + 'static {
+                type Host: Host + Send;
+            }
+            impl<F, T, O> GetHost<T> 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>(
+                linker: &mut wasmtime::component::Linker<T>,
+                host_getter: impl for<'a> GetHost<&'a mut T>,
+            ) -> wasmtime::Result<()>
+            where
+                T: Send,
+            {
+                let mut inst = linker.instance("paths:path1/test")?;
+                Ok(())
+            }
+            pub fn add_to_linker<T, U>(
+                linker: &mut wasmtime::component::Linker<T>,
+                get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+            ) -> wasmtime::Result<()>
+            where
+                U: Host + Send,
+                T: Send,
+            {
+                add_to_linker_get_host(linker, get)
+            }
+            #[wasmtime::component::__internal::async_trait]
+            impl<_T: Host + ?Sized + Send> 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
new file mode 100644
index 000000000..45f121cdd
--- /dev/null
+++ b/crates/component-macro/tests/expanded/path1_tracing_async.rs
@@ -0,0 +1,221 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Path1Indices,
+}
+impl<T> Clone for Path1Pre<T> {
+    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<Self> {
+        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<Data = _T>,
+    ) -> wasmtime::Result<Path1>
+    where
+        _T: Send,
+    {
+        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<Self> {
+            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<Self> {
+            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<Path1> {
+            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<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Path1>
+        where
+            _T: Send,
+        {
+            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<Path1> {
+            let indices = Path1Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker<T, U>(
+            linker: &mut wasmtime::component::Linker<T>,
+            get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+        ) -> wasmtime::Result<()>
+        where
+            T: Send,
+            U: paths::path1::test::Host + Send,
+        {
+            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;
+            #[wasmtime::component::__internal::async_trait]
+            pub trait Host: Send {}
+            pub trait GetHost<
+                T,
+            >: Fn(T) -> <Self as GetHost<T>>::Host + Send + Sync + Copy + 'static {
+                type Host: Host + Send;
+            }
+            impl<F, T, O> GetHost<T> 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>(
+                linker: &mut wasmtime::component::Linker<T>,
+                host_getter: impl for<'a> GetHost<&'a mut T>,
+            ) -> wasmtime::Result<()>
+            where
+                T: Send,
+            {
+                let mut inst = linker.instance("paths:path1/test")?;
+                Ok(())
+            }
+            pub fn add_to_linker<T, U>(
+                linker: &mut wasmtime::component::Linker<T>,
+                get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+            ) -> wasmtime::Result<()>
+            where
+                U: Host + Send,
+                T: Send,
+            {
+                add_to_linker_get_host(linker, get)
+            }
+            #[wasmtime::component::__internal::async_trait]
+            impl<_T: Host + ?Sized + Send> Host for &mut _T {}
+        }
+    }
+}
diff --git a/crates/component-macro/tests/expanded/path2.rs b/crates/component-macro/tests/expanded/path2.rs
new file mode 100644
index 000000000..5d9fba7b1
--- /dev/null
+++ b/crates/component-macro/tests/expanded/path2.rs
@@ -0,0 +1,208 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Path2Indices,
+}
+impl<T> Clone for Path2Pre<T> {
+    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<Self> {
+        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 fn instantiate(
+        &self,
+        mut store: impl wasmtime::AsContextMut<Data = _T>,
+    ) -> wasmtime::Result<Path2> {
+        let mut store = store.as_context_mut();
+        let instance = self.instance_pre.instantiate(&mut store)?;
+        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`] 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`] 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<Self> {
+            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<Self> {
+            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<Path2> {
+            let _instance = instance;
+            Ok(Path2 {})
+        }
+    }
+    impl Path2 {
+        /// Convenience wrapper around [`Path2Pre::new`] and
+        /// [`Path2Pre::instantiate`].
+        pub fn instantiate<_T>(
+            mut store: impl wasmtime::AsContextMut<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Path2> {
+            let pre = linker.instantiate_pre(component)?;
+            Path2Pre::new(pre)?.instantiate(store)
+        }
+        /// Convenience wrapper around [`Path2Indices::new_instance`] and
+        /// [`Path2Indices::load`].
+        pub fn new(
+            mut store: impl wasmtime::AsContextMut,
+            instance: &wasmtime::component::Instance,
+        ) -> wasmtime::Result<Path2> {
+            let indices = Path2Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker<T, U>(
+            linker: &mut wasmtime::component::Linker<T>,
+            get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+        ) -> wasmtime::Result<()>
+        where
+            U: 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;
+            pub trait Host {}
+            pub trait GetHost<
+                T,
+            >: Fn(T) -> <Self as GetHost<T>>::Host + Send + Sync + Copy + 'static {
+                type Host: Host;
+            }
+            impl<F, T, O> GetHost<T> for F
+            where
+                F: Fn(T) -> O + Send + Sync + Copy + 'static,
+                O: Host,
+            {
+                type Host = O;
+            }
+            pub fn add_to_linker_get_host<T>(
+                linker: &mut wasmtime::component::Linker<T>,
+                host_getter: impl for<'a> GetHost<&'a mut T>,
+            ) -> wasmtime::Result<()> {
+                let mut inst = linker.instance("paths:path2/test")?;
+                Ok(())
+            }
+            pub fn add_to_linker<T, U>(
+                linker: &mut wasmtime::component::Linker<T>,
+                get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+            ) -> wasmtime::Result<()>
+            where
+                U: Host,
+            {
+                add_to_linker_get_host(linker, get)
+            }
+            impl<_T: Host + ?Sized> Host for &mut _T {}
+        }
+    }
+}
diff --git a/crates/component-macro/tests/expanded/path2_async.rs b/crates/component-macro/tests/expanded/path2_async.rs
new file mode 100644
index 000000000..0e07fe478
--- /dev/null
+++ b/crates/component-macro/tests/expanded/path2_async.rs
@@ -0,0 +1,221 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Path2Indices,
+}
+impl<T> Clone for Path2Pre<T> {
+    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<Self> {
+        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<Data = _T>,
+    ) -> wasmtime::Result<Path2>
+    where
+        _T: Send,
+    {
+        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<Self> {
+            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<Self> {
+            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<Path2> {
+            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<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Path2>
+        where
+            _T: Send,
+        {
+            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<Path2> {
+            let indices = Path2Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker<T, U>(
+            linker: &mut wasmtime::component::Linker<T>,
+            get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+        ) -> wasmtime::Result<()>
+        where
+            T: Send,
+            U: paths::path2::test::Host + Send,
+        {
+            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;
+            #[wasmtime::component::__internal::async_trait]
+            pub trait Host: Send {}
+            pub trait GetHost<
+                T,
+            >: Fn(T) -> <Self as GetHost<T>>::Host + Send + Sync + Copy + 'static {
+                type Host: Host + Send;
+            }
+            impl<F, T, O> GetHost<T> 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>(
+                linker: &mut wasmtime::component::Linker<T>,
+                host_getter: impl for<'a> GetHost<&'a mut T>,
+            ) -> wasmtime::Result<()>
+            where
+                T: Send,
+            {
+                let mut inst = linker.instance("paths:path2/test")?;
+                Ok(())
+            }
+            pub fn add_to_linker<T, U>(
+                linker: &mut wasmtime::component::Linker<T>,
+                get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+            ) -> wasmtime::Result<()>
+            where
+                U: Host + Send,
+                T: Send,
+            {
+                add_to_linker_get_host(linker, get)
+            }
+            #[wasmtime::component::__internal::async_trait]
+            impl<_T: Host + ?Sized + Send> 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
new file mode 100644
index 000000000..0e07fe478
--- /dev/null
+++ b/crates/component-macro/tests/expanded/path2_tracing_async.rs
@@ -0,0 +1,221 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Path2Indices,
+}
+impl<T> Clone for Path2Pre<T> {
+    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<Self> {
+        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<Data = _T>,
+    ) -> wasmtime::Result<Path2>
+    where
+        _T: Send,
+    {
+        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<Self> {
+            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<Self> {
+            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<Path2> {
+            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<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Path2>
+        where
+            _T: Send,
+        {
+            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<Path2> {
+            let indices = Path2Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker<T, U>(
+            linker: &mut wasmtime::component::Linker<T>,
+            get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+        ) -> wasmtime::Result<()>
+        where
+            T: Send,
+            U: paths::path2::test::Host + Send,
+        {
+            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;
+            #[wasmtime::component::__internal::async_trait]
+            pub trait Host: Send {}
+            pub trait GetHost<
+                T,
+            >: Fn(T) -> <Self as GetHost<T>>::Host + Send + Sync + Copy + 'static {
+                type Host: Host + Send;
+            }
+            impl<F, T, O> GetHost<T> 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>(
+                linker: &mut wasmtime::component::Linker<T>,
+                host_getter: impl for<'a> GetHost<&'a mut T>,
+            ) -> wasmtime::Result<()>
+            where
+                T: Send,
+            {
+                let mut inst = linker.instance("paths:path2/test")?;
+                Ok(())
+            }
+            pub fn add_to_linker<T, U>(
+                linker: &mut wasmtime::component::Linker<T>,
+                get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
+            ) -> wasmtime::Result<()>
+            where
+                U: Host + Send,
+                T: Send,
+            {
+                add_to_linker_get_host(linker, get)
+            }
+            #[wasmtime::component::__internal::async_trait]
+            impl<_T: Host + ?Sized + Send> Host for &mut _T {}
+        }
+    }
+}
diff --git a/tests/all/cli_tests.rs b/tests/all/cli_tests.rs
index a8743c910..7f8b6b2f2 100644
--- a/tests/all/cli_tests.rs
+++ b/tests/all/cli_tests.rs
@@ -1098,6 +1098,21 @@ fn mpk_without_pooling() -> Result<()> {
     Ok(())
 }
 
+// Very basic use case: compile binary wasm file and run specific function with arguments.
+#[test]
+fn increase_stack_size() -> Result<()> {
+    run_wasmtime(&[
+        "run",
+        "--invoke",
+        "simple",
+        &format!("-Wmax-wasm-stack={}", 5 << 20),
+        "-Ccache=n",
+        "tests/all/cli_tests/simple.wat",
+        "4",
+    ])?;
+    Ok(())
+}
+
 mod test_programs {
     use super::{get_wasmtime_command, run_wasmtime};
     use anyhow::{bail, Context, Result};