Repository: bytecodealliance/wasmtime
Pull request #9322 (2024-09-28 15:19:46)

bug: bindgen erraneously parses extra comma
Fixes an issue introduced in #9288 where an additional comma token is erroneously consumed. This meant if path was not the last property in the bindgen options, you would see an error "expected ,"

The provided tests were simple enough that path happened to be the last property. I haven't included a new test here because I think testing for such an issue is outside the scope of the tests.


Patch:
diff --git a/crates/component-macro/src/bindgen.rs b/crates/component-macro/src/bindgen.rs
index d443748b5..9d265ee2c 100644
--- a/crates/component-macro/src/bindgen.rs
+++ b/crates/component-macro/src/bindgen.rs
@@ -328,10 +328,6 @@ impl Parse for Opt {
                 let list = Punctuated::<_, Token![,]>::parse_terminated(&contents)?;
 
                 paths.extend(list.into_iter());
-
-                if input.peek(Token![,]) {
-                    input.parse::<Token![,]>()?;
-                }
             } else {
                 return Err(l.error());
             };
diff --git a/crates/wasmtime/src/runtime/vm/const_expr.rs b/crates/wasmtime/src/runtime/vm/const_expr.rs
index 6eca60a7b..da99f9e55 100644
--- a/crates/wasmtime/src/runtime/vm/const_expr.rs
+++ b/crates/wasmtime/src/runtime/vm/const_expr.rs
@@ -5,7 +5,7 @@ use crate::store::AutoAssertNoGc;
 use crate::{prelude::*, StructRef, StructRefPre, StructType, Val};
 use smallvec::SmallVec;
 use wasmtime_environ::{
-    ConstExpr, ConstOp, FuncIndex, GlobalIndex, Module, ModuleInternedTypeIndex, WasmCompositeType,
+    ConstExpr, ConstOp, FuncIndex, GlobalIndex, ModuleInternedTypeIndex, WasmCompositeType,
     WasmSubType,
 };
 
@@ -19,15 +19,14 @@ pub struct ConstExprEvaluator {
 }
 
 /// The context within which a particular const expression is evaluated.
-pub struct ConstEvalContext<'a, 'b> {
+pub struct ConstEvalContext<'a> {
     instance: &'a mut Instance,
-    module: &'b Module,
 }
 
-impl<'a, 'b> ConstEvalContext<'a, 'b> {
+impl<'a> ConstEvalContext<'a> {
     /// Create a new context.
-    pub fn new(instance: &'a mut Instance, module: &'b Module) -> Self {
-        Self { instance, module }
+    pub fn new(instance: &'a mut Instance) -> Self {
+        Self { instance }
     }
 
     fn global_get(&mut self, store: &mut AutoAssertNoGc<'_>, index: GlobalIndex) -> Result<ValRaw> {
@@ -38,7 +37,10 @@ impl<'a, 'b> ConstEvalContext<'a, 'b> {
                 .as_ref()
                 .unwrap();
             let mut gc_store = store.unwrap_gc_store_mut();
-            Ok(global.to_val_raw(&mut gc_store, self.module.globals[index].wasm_ty))
+            Ok(global.to_val_raw(
+                &mut gc_store,
+                self.instance.env_module().globals[index].wasm_ty,
+            ))
         }
     }
 
@@ -163,7 +165,7 @@ impl ConstExprEvaluator {
     /// the correct type.
     pub unsafe fn eval(
         &mut self,
-        context: &mut ConstEvalContext<'_, '_>,
+        context: &mut ConstEvalContext<'_>,
         expr: &ConstExpr,
     ) -> Result<ValRaw> {
         self.stack.clear();
@@ -240,7 +242,8 @@ impl ConstExprEvaluator {
 
                 #[cfg(feature = "gc")]
                 ConstOp::StructNew { struct_type_index } => {
-                    let interned_type_index = context.module.types[*struct_type_index];
+                    let interned_type_index =
+                        context.instance.env_module().types[*struct_type_index];
                     let len = context.struct_fields_len(interned_type_index);
 
                     if self.stack.len() < len {
@@ -262,7 +265,8 @@ impl ConstExprEvaluator {
 
                 #[cfg(feature = "gc")]
                 ConstOp::StructNewDefault { struct_type_index } => {
-                    let interned_type_index = context.module.types[*struct_type_index];
+                    let interned_type_index =
+                        context.instance.env_module().types[*struct_type_index];
                     self.stack
                         .push(context.struct_new_default(&mut store, interned_type_index)?);
                 }
diff --git a/crates/wasmtime/src/runtime/vm/instance.rs b/crates/wasmtime/src/runtime/vm/instance.rs
index ac9c525bc..6cbf83a94 100644
--- a/crates/wasmtime/src/runtime/vm/instance.rs
+++ b/crates/wasmtime/src/runtime/vm/instance.rs
@@ -874,7 +874,7 @@ impl Instance {
                     .get(src..)
                     .and_then(|s| s.get(..len))
                     .ok_or(Trap::TableOutOfBounds)?;
-                let mut context = ConstEvalContext::new(self, &module);
+                let mut context = ConstEvalContext::new(self);
                 match module.table_plans[table_index]
                     .table
                     .ref_type
@@ -1277,7 +1277,7 @@ impl Instance {
         module: &Module,
     ) {
         for (index, init) in module.global_initializers.iter() {
-            let mut context = ConstEvalContext::new(self, module);
+            let mut context = ConstEvalContext::new(self);
             let raw = const_evaluator
                 .eval(&mut context, init)
                 .expect("should be a valid const expr");
diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator.rs
index 28a4ca843..f93592378 100644
--- a/crates/wasmtime/src/runtime/vm/instance/allocator.rs
+++ b/crates/wasmtime/src/runtime/vm/instance/allocator.rs
@@ -533,7 +533,7 @@ fn check_table_init_bounds(instance: &mut Instance, module: &Module) -> Result<(
 
     for segment in module.table_initialization.segments.iter() {
         let table = unsafe { &*instance.get_table(segment.table_index) };
-        let mut context = ConstEvalContext::new(instance, module);
+        let mut context = ConstEvalContext::new(instance);
         let start = unsafe {
             const_evaluator
                 .eval(&mut context, &segment.offset)
@@ -564,7 +564,7 @@ fn initialize_tables(instance: &mut Instance, module: &Module) -> Result<()> {
             TableInitialValue::Null { precomputed: _ } => {}
 
             TableInitialValue::Expr(expr) => {
-                let mut context = ConstEvalContext::new(instance, module);
+                let mut context = ConstEvalContext::new(instance);
                 let raw = unsafe {
                     const_evaluator
                         .eval(&mut context, expr)
@@ -607,7 +607,7 @@ fn initialize_tables(instance: &mut Instance, module: &Module) -> Result<()> {
     // iterates over all segments (Segments mode) or leftover
     // segments (FuncTable mode) to initialize.
     for segment in module.table_initialization.segments.iter() {
-        let mut context = ConstEvalContext::new(instance, module);
+        let mut context = ConstEvalContext::new(instance);
         let start = unsafe {
             const_evaluator
                 .eval(&mut context, &segment.offset)
@@ -628,12 +628,8 @@ fn initialize_tables(instance: &mut Instance, module: &Module) -> Result<()> {
     Ok(())
 }
 
-fn get_memory_init_start(
-    init: &MemoryInitializer,
-    instance: &mut Instance,
-    module: &Module,
-) -> Result<u64> {
-    let mut context = ConstEvalContext::new(instance, module);
+fn get_memory_init_start(init: &MemoryInitializer, instance: &mut Instance) -> Result<u64> {
+    let mut context = ConstEvalContext::new(instance);
     let mut const_evaluator = ConstExprEvaluator::default();
     unsafe { const_evaluator.eval(&mut context, &init.offset) }.map(|v| {
         match instance.env_module().memory_plans[init.memory_index]
@@ -648,12 +644,11 @@ fn get_memory_init_start(
 
 fn check_memory_init_bounds(
     instance: &mut Instance,
-    module: &Module,
     initializers: &[MemoryInitializer],
 ) -> Result<()> {
     for init in initializers {
         let memory = instance.get_memory(init.memory_index);
-        let start = get_memory_init_start(init, instance, module)?;
+        let start = get_memory_init_start(init, instance)?;
         let end = usize::try_from(start)
             .ok()
             .and_then(|start| start.checked_add(init.data.len()));
@@ -702,7 +697,7 @@ fn initialize_memories(instance: &mut Instance, module: &Module) -> Result<()> {
             memory: wasmtime_environ::MemoryIndex,
             expr: &wasmtime_environ::ConstExpr,
         ) -> Option<u64> {
-            let mut context = ConstEvalContext::new(self.instance, self.module);
+            let mut context = ConstEvalContext::new(self.instance);
             let val = unsafe { self.const_evaluator.eval(&mut context, expr) }
                 .expect("const expression should be valid");
             Some(
@@ -767,7 +762,7 @@ fn check_init_bounds(instance: &mut Instance, module: &Module) -> Result<()> {
 
     match &module.memory_initialization {
         MemoryInitialization::Segmented(initializers) => {
-            check_memory_init_bounds(instance, module, initializers)?;
+            check_memory_init_bounds(instance, initializers)?;
         }
         // Statically validated already to have everything in-bounds.
         MemoryInitialization::Static { .. } => {}
diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs
index 8cd6d5143..31b450875 100644
--- a/crates/wit-bindgen/src/lib.rs
+++ b/crates/wit-bindgen/src/lib.rs
@@ -2606,7 +2606,7 @@ impl<'a> InterfaceGenerator<'a> {
             FunctionKind::Freestanding => match owner {
                 TypeOwner::World(id) => format!(
                     "{}Imports",
-                    self.resolve.worlds[id].name.to_upper_camel_case()
+                    rust::to_rust_upper_camel_case(&self.resolve.worlds[id].name)
                 ),
                 _ => "Host".to_string(),
             },


Test patch:
diff --git a/crates/component-macro/tests/codegen/host-world.wit b/crates/component-macro/tests/codegen/host-world.wit
new file mode 100644
index 000000000..f2a7ca0ac
--- /dev/null
+++ b/crates/component-macro/tests/codegen/host-world.wit
@@ -0,0 +1,5 @@
+package foo:foo;
+
+world host {
+  import foo: func();
+}
\ No newline at end of file
diff --git a/crates/component-macro/tests/expanded/host-world.rs b/crates/component-macro/tests/expanded/host-world.rs
new file mode 100644
index 000000000..b5b514902
--- /dev/null
+++ b/crates/component-macro/tests/expanded/host-world.rs
@@ -0,0 +1,205 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Host_Indices,
+}
+impl<T> Clone for Host_Pre<T> {
+    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<Self> {
+        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 fn instantiate(
+        &self,
+        mut store: impl wasmtime::AsContextMut<Data = _T>,
+    ) -> wasmtime::Result<Host_> {
+        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
+/// `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`] 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`] 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 {
+    fn foo(&mut self) -> ();
+}
+pub trait Host_ImportsGetHost<
+    T,
+>: Fn(T) -> <Self as Host_ImportsGetHost<T>>::Host + Send + Sync + Copy + 'static {
+    type Host: Host_Imports;
+}
+impl<F, T, O> Host_ImportsGetHost<T> for F
+where
+    F: Fn(T) -> O + Send + Sync + Copy + 'static,
+    O: Host_Imports,
+{
+    type Host = O;
+}
+impl<_T: Host_Imports + ?Sized> Host_Imports for &mut _T {
+    fn foo(&mut self) -> () {
+        Host_Imports::foo(*self)
+    }
+}
+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<Self> {
+            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<Self> {
+            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<Host_> {
+            let _instance = instance;
+            Ok(Host_ {})
+        }
+    }
+    impl Host_ {
+        /// Convenience wrapper around [`Host_Pre::new`] and
+        /// [`Host_Pre::instantiate`].
+        pub fn instantiate<_T>(
+            mut store: impl wasmtime::AsContextMut<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Host_> {
+            let pre = linker.instantiate_pre(component)?;
+            Host_Pre::new(pre)?.instantiate(store)
+        }
+        /// 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<Host_> {
+            let indices = Host_Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker_imports_get_host<T>(
+            linker: &mut wasmtime::component::Linker<T>,
+            host_getter: impl for<'a> Host_ImportsGetHost<&'a mut T>,
+        ) -> wasmtime::Result<()> {
+            let mut linker = linker.root();
+            linker
+                .func_wrap(
+                    "foo",
+                    move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| {
+                        let host = &mut host_getter(caller.data_mut());
+                        let r = Host_Imports::foo(host);
+                        Ok(r)
+                    },
+                )?;
+            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_Imports,
+        {
+            Self::add_to_linker_imports_get_host(linker, get)?;
+            Ok(())
+        }
+    }
+};
diff --git a/crates/component-macro/tests/expanded/host-world_async.rs b/crates/component-macro/tests/expanded/host-world_async.rs
new file mode 100644
index 000000000..79226375a
--- /dev/null
+++ b/crates/component-macro/tests/expanded/host-world_async.rs
@@ -0,0 +1,219 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Host_Indices,
+}
+impl<T> Clone for Host_Pre<T> {
+    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<Self> {
+        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<Data = _T>,
+    ) -> wasmtime::Result<Host_>
+    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
+/// `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_ {}
+#[wasmtime::component::__internal::async_trait]
+pub trait Host_Imports: Send {
+    async fn foo(&mut self) -> ();
+}
+pub trait Host_ImportsGetHost<
+    T,
+>: Fn(T) -> <Self as Host_ImportsGetHost<T>>::Host + Send + Sync + Copy + 'static {
+    type Host: Host_Imports;
+}
+impl<F, T, O> Host_ImportsGetHost<T> for F
+where
+    F: Fn(T) -> O + Send + Sync + Copy + 'static,
+    O: Host_Imports,
+{
+    type Host = O;
+}
+#[wasmtime::component::__internal::async_trait]
+impl<_T: Host_Imports + ?Sized + Send> Host_Imports for &mut _T {
+    async fn foo(&mut self) -> () {
+        Host_Imports::foo(*self).await
+    }
+}
+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<Self> {
+            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<Self> {
+            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<Host_> {
+            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<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Host_>
+        where
+            _T: Send,
+        {
+            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<Host_> {
+            let indices = Host_Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker_imports_get_host<T>(
+            linker: &mut wasmtime::component::Linker<T>,
+            host_getter: impl for<'a> Host_ImportsGetHost<&'a mut T>,
+        ) -> wasmtime::Result<()>
+        where
+            T: Send,
+        {
+            let mut linker = linker.root();
+            linker
+                .func_wrap_async(
+                    "foo",
+                    move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| {
+                        wasmtime::component::__internal::Box::new(async move {
+                            let host = &mut host_getter(caller.data_mut());
+                            let r = Host_Imports::foo(host).await;
+                            Ok(r)
+                        })
+                    },
+                )?;
+            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
+            T: Send,
+            U: Host_Imports + Send,
+        {
+            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
new file mode 100644
index 000000000..9ded0ccb6
--- /dev/null
+++ b/crates/component-macro/tests/expanded/host-world_tracing_async.rs
@@ -0,0 +1,232 @@
+/// 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<T> {
+    instance_pre: wasmtime::component::InstancePre<T>,
+    indices: Host_Indices,
+}
+impl<T> Clone for Host_Pre<T> {
+    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<Self> {
+        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<Data = _T>,
+    ) -> wasmtime::Result<Host_>
+    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
+/// `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_ {}
+#[wasmtime::component::__internal::async_trait]
+pub trait Host_Imports: Send {
+    async fn foo(&mut self) -> ();
+}
+pub trait Host_ImportsGetHost<
+    T,
+>: Fn(T) -> <Self as Host_ImportsGetHost<T>>::Host + Send + Sync + Copy + 'static {
+    type Host: Host_Imports;
+}
+impl<F, T, O> Host_ImportsGetHost<T> for F
+where
+    F: Fn(T) -> O + Send + Sync + Copy + 'static,
+    O: Host_Imports,
+{
+    type Host = O;
+}
+#[wasmtime::component::__internal::async_trait]
+impl<_T: Host_Imports + ?Sized + Send> Host_Imports for &mut _T {
+    async fn foo(&mut self) -> () {
+        Host_Imports::foo(*self).await
+    }
+}
+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<Self> {
+            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<Self> {
+            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<Host_> {
+            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<Data = _T>,
+            component: &wasmtime::component::Component,
+            linker: &wasmtime::component::Linker<_T>,
+        ) -> wasmtime::Result<Host_>
+        where
+            _T: Send,
+        {
+            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<Host_> {
+            let indices = Host_Indices::new_instance(&mut store, instance)?;
+            indices.load(store, instance)
+        }
+        pub fn add_to_linker_imports_get_host<T>(
+            linker: &mut wasmtime::component::Linker<T>,
+            host_getter: impl for<'a> Host_ImportsGetHost<&'a mut T>,
+        ) -> wasmtime::Result<()>
+        where
+            T: Send,
+        {
+            let mut linker = linker.root();
+            linker
+                .func_wrap_async(
+                    "foo",
+                    move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| {
+                        use tracing::Instrument;
+                        let span = tracing::span!(
+                            tracing::Level::TRACE, "wit-bindgen import", module = "host",
+                            function = "foo",
+                        );
+                        wasmtime::component::__internal::Box::new(
+                            async move {
+                                tracing::event!(tracing::Level::TRACE, "call");
+                                let host = &mut host_getter(caller.data_mut());
+                                let r = Host_Imports::foo(host).await;
+                                tracing::event!(
+                                    tracing::Level::TRACE, result = tracing::field::debug(& r),
+                                    "return"
+                                );
+                                Ok(r)
+                            }
+                                .instrument(span),
+                        )
+                    },
+                )?;
+            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
+            T: Send,
+            U: Host_Imports + Send,
+        {
+            Self::add_to_linker_imports_get_host(linker, get)?;
+            Ok(())
+        }
+    }
+};