Repository: bytecodealliance/wasm-tools
Pull request #2091 (2025-03-11 15:09:10)

wit-component: Eagerly define all exported types
This commit fixes an assertion failure found via the fuzzing of wit-component. The basic problem is that the `task.return` intrinsic, and other async intrinsics, need to refer to asynchronous types to be declared, but while defining some types can be done lazily it's not always easy to do so. Currently all types are defined lazily as the intrinsic is declared, but this panics when referring to types defined in other interfaces as the current type-defining machinery (rightfully) panics in this situation.

The fix applied in this commit is to update the part of encoding which eagerly defines type information for imported intrinsics, previously just resources, to now also define all types for exported interfaces. This ensures that all defined types necessary will already be available by the time that intrinsics are defined. Overall `wit-component` is definitely in need of cleaning up how types are defined, but for now that's left for a future refactoring...

Otherwise some test expectations are also changing here in this commit as types were shuffled around and a few dead types were also generated.


Patch:
diff --git a/crates/wasmparser/src/validator/core/canonical.rs b/crates/wasmparser/src/validator/core/canonical.rs
index b109eb75..67f6a94c 100644
--- a/crates/wasmparser/src/validator/core/canonical.rs
+++ b/crates/wasmparser/src/validator/core/canonical.rs
@@ -388,14 +388,21 @@ impl<'a> TypeCanonicalizer<'a> {
                 // typed function references proposal, only the GC proposal.
                 debug_assert!(self.allow_gc() || self.rec_group_len == 1);
                 let local = index - self.rec_group_start;
-                if self.allow_gc() && local < self.rec_group_len {
-                    if let Some(id) = PackedIndex::from_rec_group_index(local) {
-                        *ty = id;
-                        return Ok(());
+                if local < self.rec_group_len {
+                    if self.allow_gc() {
+                        if let Some(id) = PackedIndex::from_rec_group_index(local) {
+                            *ty = id;
+                            return Ok(());
+                        } else {
+                            bail!(
+                                self.offset,
+                                "implementation limit: too many types in a recursion group"
+                            )
+                        }
                     } else {
                         bail!(
                             self.offset,
-                            "implementation limit: too many types in a recursion group"
+                            "unknown type {index}: type index out of bounds because the GC proposal is disabled"
                         )
                     }
                 }
diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs
index 3e458ba2..979e4c77 100644
--- a/crates/wit-component/src/encoding.rs
+++ b/crates/wit-component/src/encoding.rs
@@ -569,10 +569,10 @@ impl<'a> EncodingState<'a> {
         // Encode a shim instantiation if needed
         let shims = self.encode_shim_instantiation()?;
 
-        // Next declare all exported resource types. This populates
-        // `export_type_map` and will additionally be used for imports to
-        // modules instantiated below.
-        self.declare_exported_resources(&shims);
+        // Next declare any types needed for imported intrinsics. This
+        // populates `export_type_map` and will additionally be used for
+        // imports to modules instantiated below.
+        self.declare_types_for_imported_intrinsics(&shims)?;
 
         // Next instantiate the main module. This provides the linear memory to
         // use for all future adapters and enables creating indirect lowerings
@@ -1418,19 +1418,18 @@ impl<'a> EncodingState<'a> {
         Ok(type_index)
     }
 
-    /// This is a helper function that will declare, in the component itself,
-    /// all exported resources.
+    /// This is a helper function that will declare any types necessary for
+    /// declaring intrinsics that are imported into the module or adapter.
     ///
-    /// These resources later on get packaged up into instances and such. The
-    /// main thing that this handles is that it registers the right destructor
-    /// from `shims`, if needed, for each resource.
-    fn declare_exported_resources(&mut self, shims: &Shims<'_>) {
+    /// For example resources must be declared to generate
+    /// destructors/constructors/etc. Additionally types must also be declared
+    /// for `task.return` with the component model async feature.
+    fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
         let resolve = &self.info.encoder.metadata.resolve;
         let world = &resolve.worlds[self.info.encoder.metadata.world];
 
         // Iterate over the main module's exports and the exports of all
-        // adapters. Look for exported interfaces that themselves have
-        // resources.
+        // adapters. Look for exported interfaces.
         let main_module_keys = self.info.encoder.main_module_exports.iter();
         let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
         let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
@@ -1446,32 +1445,39 @@ impl<'a> EncodingState<'a> {
             };
 
             for ty in resolve.interfaces[id].types.values() {
-                match resolve.types[*ty].kind {
-                    TypeDefKind::Resource => {}
-                    _ => continue,
-                }
-
-                // Load the destructor, previously detected in module
-                // validation, if one is present.
-                let exports = self.info.exports_for(for_module);
-                let dtor = exports.resource_dtor(*ty).map(|name| {
-                    let name = &shims.shims[&ShimKind::ResourceDtor {
-                        module: for_module,
-                        export: name,
-                    }]
-                        .name;
-                    let shim = self.shim_instance_index.unwrap();
-                    self.core_alias_export(shim, name, ExportKind::Func)
-                });
+                match &resolve.types[*ty].kind {
+                    // Declare exported resources specially as they generally
+                    // need special treatment for later handling exports and
+                    // such.
+                    TypeDefKind::Resource => {
+                        // Load the destructor, previously detected in module
+                        // validation, if one is present.
+                        let exports = self.info.exports_for(for_module);
+                        let dtor = exports.resource_dtor(*ty).map(|name| {
+                            let name = &shims.shims[&ShimKind::ResourceDtor {
+                                module: for_module,
+                                export: name,
+                            }]
+                                .name;
+                            let shim = self.shim_instance_index.unwrap();
+                            self.core_alias_export(shim, name, ExportKind::Func)
+                        });
 
-                // Declare the resource with this destructor and register it in
-                // our internal map. This should be the first and only time this
-                // type is inserted into this map.
-                let resource_idx = self.component.type_resource(ValType::I32, dtor);
-                let prev = self.export_type_map.insert(*ty, resource_idx);
-                assert!(prev.is_none());
+                        // Declare the resource with this destructor and register it in
+                        // our internal map. This should be the first and only time this
+                        // type is inserted into this map.
+                        let resource_idx = self.component.type_resource(ValType::I32, dtor);
+                        let prev = self.export_type_map.insert(*ty, resource_idx);
+                        assert!(prev.is_none());
+                    }
+                    _other => {
+                        self.root_export_type_encoder(Some(id))
+                            .encode_valtype(resolve, &Type::Id(*ty))?;
+                    }
+                }
             }
         }
+        Ok(())
     }
 
     /// Helper to instantiate the main module and record various results of its
@@ -1605,7 +1611,7 @@ impl<'a> EncodingState<'a> {
             // an exported resource the component still provides necessary
             // intrinsics for manipulating resource state. These are all
             // handled here using the resource types created during
-            // `declare_exported_resources` above.
+            // `declare_types_for_imported_intrinsics` above.
             Import::ExportedResourceDrop(_key, id) => {
                 let index = self.component.resource_drop(self.export_type_map[id]);
                 Ok((ExportKind::Func, index))


Test patch:
diff --git a/crates/wit-component/tests/components/export-interface-using-import/component.wat b/crates/wit-component/tests/components/export-interface-using-import/component.wat
index f48fcc78..41b5ab91 100644
--- a/crates/wit-component/tests/components/export-interface-using-import/component.wat
+++ b/crates/wit-component/tests/components/export-interface-using-import/component.wat
@@ -14,9 +14,10 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
+  (alias export 0 "r" (type (;1;)))
   (core instance (;0;) (instantiate 0))
-  (alias export 0 "f" (type (;1;)))
-  (alias export 0 "r" (type (;2;)))
+  (alias export 0 "f" (type (;2;)))
+  (alias export 0 "r" (type (;3;)))
   (component (;0;)
     (type (;0;) (record (field "f" u32)))
     (import "import-type-f" (type (;1;) (eq 0)))
@@ -25,8 +26,8 @@
     (export (;4;) "r" (type 3))
   )
   (instance (;1;) (instantiate 0
-      (with "import-type-f" (type 1))
-      (with "import-type-r" (type 2))
+      (with "import-type-f" (type 2))
+      (with "import-type-r" (type 3))
     )
   )
   (export (;2;) "x" (instance 1))
diff --git a/crates/wit-component/tests/components/export-name-shuffling/component.wat b/crates/wit-component/tests/components/export-name-shuffling/component.wat
index 433bb76e..b101c100 100644
--- a/crates/wit-component/tests/components/export-name-shuffling/component.wat
+++ b/crates/wit-component/tests/components/export-name-shuffling/component.wat
@@ -8,6 +8,7 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
+  (type (;0;) (record (field "f" u32)))
   (core instance (;0;) (instantiate 0))
   (component (;0;)
     (type (;0;) (record (field "f" u32)))
@@ -15,10 +16,10 @@
   )
   (instance (;0;) (instantiate 0))
   (export (;1;) "foo:foo/name" (instance 0))
-  (alias export 1 "foo" (type (;0;)))
   (type (;1;) (func (param "f" 0)))
   (alias core export 0 "name#a" (core func (;0;)))
   (func (;0;) (type 1) (canon lift (core func 0)))
+  (alias export 1 "foo" (type (;2;)))
   (component (;1;)
     (type (;0;) (record (field "f" u32)))
     (import "import-type-foo" (type (;1;) (eq 0)))
@@ -31,7 +32,7 @@
   )
   (instance (;2;) (instantiate 1
       (with "import-func-a" (func 0))
-      (with "import-type-foo" (type 0))
+      (with "import-type-foo" (type 2))
       (with "import-type-foo0" (type 0))
     )
   )
diff --git a/crates/wit-component/tests/components/export-type-name-conflict/component.wat b/crates/wit-component/tests/components/export-type-name-conflict/component.wat
index 67ad5cb6..ba7848b6 100644
--- a/crates/wit-component/tests/components/export-type-name-conflict/component.wat
+++ b/crates/wit-component/tests/components/export-type-name-conflict/component.wat
@@ -17,8 +17,8 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
-  (core instance (;0;) (instantiate 0))
   (alias export 0 "foo" (type (;1;)))
+  (core instance (;0;) (instantiate 0))
   (type (;2;) (func (result 1)))
   (alias core export 0 "bar#foo" (core func (;0;)))
   (func (;0;) (type 2) (canon lift (core func 0)))
diff --git a/crates/wit-component/tests/components/export-with-type-alias/component.wat b/crates/wit-component/tests/components/export-with-type-alias/component.wat
index 5da0178d..e44abab7 100644
--- a/crates/wit-component/tests/components/export-with-type-alias/component.wat
+++ b/crates/wit-component/tests/components/export-with-type-alias/component.wat
@@ -10,8 +10,8 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
-  (core instance (;0;) (instantiate 0))
   (type (;0;) u8)
+  (core instance (;0;) (instantiate 0))
   (type (;1;) (func (param "a" 0) (result 0)))
   (alias core export 0 "foo:foo/foo#c" (core func (;0;)))
   (func (;0;) (type 1) (canon lift (core func 0)))
diff --git a/crates/wit-component/tests/components/exports/component.wat b/crates/wit-component/tests/components/exports/component.wat
index 1410510f..d1775e32 100644
--- a/crates/wit-component/tests/components/exports/component.wat
+++ b/crates/wit-component/tests/components/exports/component.wat
@@ -58,27 +58,28 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
+  (type (;0;) (flags "a" "b" "c"))
+  (type (;1;) (variant (case "a") (case "b" string) (case "c" s64)))
   (core instance (;0;) (instantiate 0))
   (alias core export 0 "memory" (core memory (;0;)))
-  (type (;0;) (func))
+  (type (;2;) (func))
   (alias core export 0 "a" (core func (;0;)))
   (alias core export 0 "cabi_realloc" (core func (;1;)))
-  (func (;0;) (type 0) (canon lift (core func 0)))
+  (func (;0;) (type 2) (canon lift (core func 0)))
   (export (;1;) "a" (func 0))
-  (type (;1;) (func (param "a" s8) (param "b" s16) (param "c" s32) (param "d" s64) (result string)))
+  (type (;3;) (func (param "a" s8) (param "b" s16) (param "c" s32) (param "d" s64) (result string)))
   (alias core export 0 "b" (core func (;2;)))
   (alias core export 0 "cabi_post_b" (core func (;3;)))
-  (func (;2;) (type 1) (canon lift (core func 2) (memory 0) string-encoding=utf8 (post-return 3)))
+  (func (;2;) (type 3) (canon lift (core func 2) (memory 0) string-encoding=utf8 (post-return 3)))
   (export (;3;) "b" (func 2))
-  (type (;2;) (tuple s8 s16 s32 s64))
-  (type (;3;) (func (result 2)))
+  (type (;4;) (tuple s8 s16 s32 s64))
+  (type (;5;) (func (result 4)))
   (alias core export 0 "c" (core func (;4;)))
-  (func (;4;) (type 3) (canon lift (core func 4) (memory 0)))
+  (func (;4;) (type 5) (canon lift (core func 4) (memory 0)))
   (export (;5;) "c" (func 4))
-  (type (;4;) (flags "a" "b" "c"))
-  (type (;5;) (func (param "x" 4)))
+  (type (;6;) (func (param "x" 0)))
   (alias core export 0 "bar#a" (core func (;5;)))
-  (func (;6;) (type 5) (canon lift (core func 5)))
+  (func (;6;) (type 6) (canon lift (core func 5)))
   (component (;0;)
     (type (;0;) (flags "a" "b" "c"))
     (import "import-type-x" (type (;1;) (eq 0)))
@@ -91,19 +92,18 @@
   )
   (instance (;0;) (instantiate 0
       (with "import-func-a" (func 6))
-      (with "import-type-x" (type 4))
+      (with "import-type-x" (type 0))
     )
   )
   (export (;1;) "bar" (instance 0))
-  (type (;6;) (func))
+  (type (;7;) (func))
   (alias core export 0 "foo#a" (core func (;6;)))
-  (func (;7;) (type 6) (canon lift (core func 6)))
-  (type (;7;) (variant (case "a") (case "b" string) (case "c" s64)))
-  (type (;8;) (func (param "x" string) (result 7)))
+  (func (;7;) (type 7) (canon lift (core func 6)))
+  (type (;8;) (func (param "x" string) (result 1)))
   (alias core export 0 "foo#b" (core func (;7;)))
   (alias core export 0 "cabi_post_foo#b" (core func (;8;)))
   (func (;8;) (type 8) (canon lift (core func 7) (memory 0) (realloc 1) string-encoding=utf8 (post-return 8)))
-  (type (;9;) (func (param "x" 7) (result string)))
+  (type (;9;) (func (param "x" 1) (result string)))
   (alias core export 0 "foo#c" (core func (;9;)))
   (alias core export 0 "cabi_post_foo#c" (core func (;10;)))
   (func (;9;) (type 9) (canon lift (core func 9) (memory 0) (realloc 1) string-encoding=utf8 (post-return 10)))
@@ -129,7 +129,7 @@
       (with "import-func-a" (func 7))
       (with "import-func-b" (func 8))
       (with "import-func-c" (func 9))
-      (with "import-type-x" (type 7))
+      (with "import-type-x" (type 1))
     )
   )
   (export (;3;) "foo" (instance 2))
diff --git a/crates/wit-component/tests/components/import-partial-export-full/component.wat b/crates/wit-component/tests/components/import-partial-export-full/component.wat
index fe0ee172..2f180b3d 100644
--- a/crates/wit-component/tests/components/import-partial-export-full/component.wat
+++ b/crates/wit-component/tests/components/import-partial-export-full/component.wat
@@ -15,6 +15,9 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
+  (type (;3;) (list string))
+  (type (;4;) (variant (case "num" u16) (case "strs" 3)))
+  (type (;5;) (variant (case "strs" 3)))
   (core instance (;0;) (instantiate 0))
   (component (;0;)
     (type (;0;) (list string))
diff --git a/crates/wit-component/tests/components/lift-options/component.wat b/crates/wit-component/tests/components/lift-options/component.wat
index f56c0b8b..97937b7a 100644
--- a/crates/wit-component/tests/components/lift-options/component.wat
+++ b/crates/wit-component/tests/components/lift-options/component.wat
@@ -97,37 +97,37 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
+  (type (;0;) (record (field "s" string)))
+  (type (;1;) (record (field "s" u32)))
+  (type (;2;) (variant (case "s" string)))
+  (type (;3;) (variant (case "s" u32)))
   (core instance (;0;) (instantiate 0))
   (alias core export 0 "memory" (core memory (;0;)))
-  (type (;0;) (func))
+  (type (;4;) (func))
   (alias core export 0 "foo:foo/my-default#a" (core func (;0;)))
   (alias core export 0 "cabi_realloc" (core func (;1;)))
-  (func (;0;) (type 0) (canon lift (core func 0)))
-  (type (;1;) (list string))
-  (type (;2;) (func (param "x" 1)))
+  (func (;0;) (type 4) (canon lift (core func 0)))
+  (type (;5;) (list string))
+  (type (;6;) (func (param "x" 5)))
   (alias core export 0 "foo:foo/my-default#b" (core func (;2;)))
-  (func (;1;) (type 2) (canon lift (core func 2) (memory 0) (realloc 1) string-encoding=utf8))
-  (type (;3;) (record (field "s" string)))
-  (type (;4;) (func (param "x" 3)))
+  (func (;1;) (type 6) (canon lift (core func 2) (memory 0) (realloc 1) string-encoding=utf8))
+  (type (;7;) (func (param "x" 0)))
   (alias core export 0 "foo:foo/my-default#c" (core func (;3;)))
-  (func (;2;) (type 4) (canon lift (core func 3) (memory 0) (realloc 1) string-encoding=utf8))
-  (type (;5;) (variant (case "s" string)))
-  (type (;6;) (func (param "x" 5)))
+  (func (;2;) (type 7) (canon lift (core func 3) (memory 0) (realloc 1) string-encoding=utf8))
+  (type (;8;) (func (param "x" 2)))
   (alias core export 0 "foo:foo/my-default#d" (core func (;4;)))
-  (func (;3;) (type 6) (canon lift (core func 4) (memory 0) (realloc 1) string-encoding=utf8))
-  (type (;7;) (record (field "s" u32)))
-  (type (;8;) (func (param "x" 7)))
+  (func (;3;) (type 8) (canon lift (core func 4) (memory 0) (realloc 1) string-encoding=utf8))
+  (type (;9;) (func (param "x" 1)))
   (alias core export 0 "foo:foo/my-default#e" (core func (;5;)))
-  (func (;4;) (type 8) (canon lift (core func 5)))
-  (type (;9;) (variant (case "s" u32)))
-  (type (;10;) (func (param "x" 9)))
+  (func (;4;) (type 9) (canon lift (core func 5)))
+  (type (;10;) (func (param "x" 3)))
   (alias core export 0 "foo:foo/my-default#f" (core func (;6;)))
   (func (;5;) (type 10) (canon lift (core func 6)))
-  (type (;11;) (list 3))
+  (type (;11;) (list 0))
   (type (;12;) (func (param "x" 11)))
   (alias core export 0 "foo:foo/my-default#g" (core func (;7;)))
   (func (;6;) (type 12) (canon lift (core func 7) (memory 0) (realloc 1) string-encoding=utf8))
-  (type (;13;) (list 5))
+  (type (;13;) (list 2))
   (type (;14;) (func (param "x" 13)))
   (alias core export 0 "foo:foo/my-default#h" (core func (;8;)))
   (func (;7;) (type 14) (canon lift (core func 8) (memory 0) (realloc 1) string-encoding=utf8))
@@ -153,11 +153,11 @@
   (type (;22;) (func (result u32)))
   (alias core export 0 "foo:foo/my-default#n" (core func (;16;)))
   (func (;13;) (type 22) (canon lift (core func 16)))
-  (type (;23;) (func (result 5)))
+  (type (;23;) (func (result 2)))
   (alias core export 0 "foo:foo/my-default#o" (core func (;17;)))
   (alias core export 0 "cabi_post_foo:foo/my-default#o" (core func (;18;)))
   (func (;14;) (type 23) (canon lift (core func 17) (memory 0) string-encoding=utf8 (post-return 18)))
-  (type (;24;) (list 9))
+  (type (;24;) (list 3))
   (type (;25;) (func (result 24)))
   (alias core export 0 "foo:foo/my-default#p" (core func (;19;)))
   (alias core export 0 "cabi_post_foo:foo/my-default#p" (core func (;20;)))
@@ -273,10 +273,10 @@
       (with "import-func-n" (func 13))
       (with "import-func-o" (func 14))
       (with "import-func-p" (func 15))
-      (with "import-type-r" (type 3))
-      (with "import-type-v" (type 5))
-      (with "import-type-r-no-string" (type 7))
-      (with "import-type-v-no-string" (type 9))
+      (with "import-type-r" (type 0))
+      (with "import-type-v" (type 2))
+      (with "import-type-r-no-string" (type 1))
+      (with "import-type-v-no-string" (type 3))
     )
   )
   (export (;1;) "foo:foo/my-default" (instance 0))
diff --git a/crates/wit-component/tests/components/many-same-names/component.wat b/crates/wit-component/tests/components/many-same-names/component.wat
index 2ad6f022..f88bb0b9 100644
--- a/crates/wit-component/tests/components/many-same-names/component.wat
+++ b/crates/wit-component/tests/components/many-same-names/component.wat
@@ -8,6 +8,8 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
+  (type (;0;) (record (field "f" u8)))
+  (type (;1;) (record (field "x" 0)))
   (core instance (;0;) (instantiate 0))
   (component (;0;)
     (type (;0;) (record (field "f" u8)))
@@ -17,11 +19,11 @@
   )
   (instance (;0;) (instantiate 0))
   (export (;1;) "foo:foo/name" (instance 0))
-  (type (;0;) (func))
+  (type (;2;) (func))
   (alias core export 0 "name#a" (core func (;0;)))
-  (func (;0;) (type 0) (canon lift (core func 0)))
-  (alias export 1 "r1" (type (;1;)))
-  (alias export 1 "r2" (type (;2;)))
+  (func (;0;) (type 2) (canon lift (core func 0)))
+  (alias export 1 "r1" (type (;3;)))
+  (alias export 1 "r2" (type (;4;)))
   (component (;1;)
     (type (;0;) (record (field "f" u8)))
     (import "import-type-r1" (type (;1;) (eq 0)))
@@ -35,8 +37,8 @@
   )
   (instance (;2;) (instantiate 1
       (with "import-func-a" (func 0))
-      (with "import-type-r1" (type 1))
-      (with "import-type-r2" (type 2))
+      (with "import-type-r1" (type 3))
+      (with "import-type-r2" (type 4))
     )
   )
   (export (;3;) "name" (instance 2))
diff --git a/crates/wit-component/tests/components/resource-used-through-import/component.wat b/crates/wit-component/tests/components/resource-used-through-import/component.wat
index 453afd16..2be511bb 100644
--- a/crates/wit-component/tests/components/resource-used-through-import/component.wat
+++ b/crates/wit-component/tests/components/resource-used-through-import/component.wat
@@ -19,7 +19,8 @@
     )
   )
   (alias export 0 "r" (type (;1;)))
-  (core func (;0;) (canon resource.drop 1))
+  (alias export 0 "r" (type (;2;)))
+  (core func (;0;) (canon resource.drop 2))
   (core instance (;0;)
     (export "[resource-drop]r" (func 0))
   )
@@ -27,8 +28,7 @@
       (with "foo:bar/a" (instance 0))
     )
   )
-  (alias export 0 "r" (type (;2;)))
-  (type (;3;) (own 2))
+  (type (;3;) (own 1))
   (type (;4;) (func (result 3)))
   (alias core export 1 "b#foo" (core func (;1;)))
   (func (;0;) (type 4) (canon lift (core func 1)))
@@ -47,7 +47,7 @@
   (instance (;1;) (instantiate 0
       (with "import-func-foo" (func 0))
       (with "import-type-r" (type 5))
-      (with "import-type-r0" (type 2))
+      (with "import-type-r0" (type 1))
     )
   )
   (export (;2;) "b" (instance 1))
diff --git a/crates/wit-component/tests/components/resource-using-export/component.wat b/crates/wit-component/tests/components/resource-using-export/component.wat
index dbd17dd4..d9784004 100644
--- a/crates/wit-component/tests/components/resource-using-export/component.wat
+++ b/crates/wit-component/tests/components/resource-using-export/component.wat
@@ -14,6 +14,7 @@
     )
   )
   (type (;0;) (resource (rep i32)))
+  (type (;1;) (own 0))
   (core func (;0;) (canon resource.new 0))
   (core instance (;0;)
     (export "[resource-new]r" (func 0))
@@ -33,11 +34,11 @@
     )
   )
   (export (;1;) "foo:bar/foo" (instance 0))
-  (alias export 1 "handle" (type (;1;)))
   (type (;2;) (func (result 1)))
   (alias core export 1 "anon#f" (core func (;1;)))
   (func (;0;) (type 2) (canon lift (core func 1)))
   (alias export 1 "r" (type (;3;)))
+  (alias export 1 "handle" (type (;4;)))
   (component (;1;)
     (import "import-type-r" (type (;0;) (sub resource)))
     (type (;1;) (own 0))
@@ -52,7 +53,7 @@
   (instance (;2;) (instantiate 1
       (with "import-func-f" (func 0))
       (with "import-type-r" (type 3))
-      (with "import-type-handle" (type 1))
+      (with "import-type-handle" (type 4))
       (with "import-type-handle0" (type 1))
     )
   )
diff --git a/crates/wit-component/tests/components/tricky-order/component.wat b/crates/wit-component/tests/components/tricky-order/component.wat
index a0b96e4a..98076725 100644
--- a/crates/wit-component/tests/components/tricky-order/component.wat
+++ b/crates/wit-component/tests/components/tricky-order/component.wat
@@ -20,9 +20,11 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
-  (core instance (;0;) (instantiate 0))
   (alias export 0 "name" (type (;3;)))
   (alias export 1 "name" (type (;4;)))
+  (core instance (;0;) (instantiate 0))
+  (alias export 0 "name" (type (;5;)))
+  (alias export 1 "name" (type (;6;)))
   (component (;0;)
     (type (;0;) (record (field "f" u8)))
     (import "import-type-name" (type (;1;) (eq 0)))
@@ -31,8 +33,8 @@
     (export (;4;) "name1" (type 2))
   )
   (instance (;2;) (instantiate 0
-      (with "import-type-name" (type 3))
-      (with "import-type-name0" (type 4))
+      (with "import-type-name" (type 5))
+      (with "import-type-name0" (type 6))
     )
   )
   (export (;3;) "name" (instance 2))
diff --git a/crates/wit-component/tests/components/tricky-resources/component.wat b/crates/wit-component/tests/components/tricky-resources/component.wat
index cb5c187a..9c6ab240 100644
--- a/crates/wit-component/tests/components/tricky-resources/component.wat
+++ b/crates/wit-component/tests/components/tricky-resources/component.wat
@@ -44,11 +44,11 @@
     )
   )
   (export (;3;) "foo:bar/b" (instance 2))
-  (alias export 3 "r" (type (;2;)))
-  (type (;3;) (own 2))
-  (type (;4;) (func (result 3)))
+  (type (;2;) (own 0))
+  (type (;3;) (func (result 2)))
   (alias core export 1 "some-name#f" (core func (;2;)))
-  (func (;0;) (type 4) (canon lift (core func 2)))
+  (func (;0;) (type 3) (canon lift (core func 2)))
+  (alias export 3 "r" (type (;4;)))
   (component (;2;)
     (import "import-type-r" (type (;0;) (sub resource)))
     (import "import-type-r0" (type (;1;) (eq 0)))
@@ -64,8 +64,8 @@
   (instance (;4;) (instantiate 2
       (with "import-func-f" (func 0))
       (with "import-type-r" (type 1))
-      (with "import-type-r0" (type 2))
-      (with "import-type-r01" (type 2))
+      (with "import-type-r0" (type 4))
+      (with "import-type-r01" (type 0))
     )
   )
   (export (;5;) "some-name" (instance 4))
diff --git a/crates/wit-component/tests/components/tricky-resources2/component.wat b/crates/wit-component/tests/components/tricky-resources2/component.wat
index db068875..df34edb1 100644
--- a/crates/wit-component/tests/components/tricky-resources2/component.wat
+++ b/crates/wit-component/tests/components/tricky-resources2/component.wat
@@ -21,11 +21,11 @@
     )
   )
   (export (;1;) "foo:bar/a" (instance 0))
-  (alias export 1 "r" (type (;1;)))
-  (type (;2;) (own 1))
-  (type (;3;) (func (result 2)))
+  (type (;1;) (own 0))
+  (type (;2;) (func (result 1)))
   (alias core export 0 "anon#foo" (core func (;0;)))
-  (func (;0;) (type 3) (canon lift (core func 0)))
+  (func (;0;) (type 2) (canon lift (core func 0)))
+  (alias export 1 "r" (type (;3;)))
   (component (;1;)
     (import "import-type-r" (type (;0;) (sub resource)))
     (import "import-type-r0" (type (;1;) (eq 0)))
@@ -39,8 +39,8 @@
   )
   (instance (;2;) (instantiate 1
       (with "import-func-foo" (func 0))
-      (with "import-type-r" (type 1))
-      (with "import-type-r0" (type 1))
+      (with "import-type-r" (type 3))
+      (with "import-type-r0" (type 0))
     )
   )
   (export (;3;) "anon" (instance 2))
diff --git a/crates/wit-component/tests/components/worlds-with-type-renamings/component.wat b/crates/wit-component/tests/components/worlds-with-type-renamings/component.wat
index 5e72b526..ffbd93c4 100644
--- a/crates/wit-component/tests/components/worlds-with-type-renamings/component.wat
+++ b/crates/wit-component/tests/components/worlds-with-type-renamings/component.wat
@@ -30,6 +30,7 @@
       (processed-by "my-fake-bindgen" "123.45")
     )
   )
+  (type (;3;) (record (field "f" u8)))
   (alias export 0 "the-func" (func (;0;)))
   (core func (;0;) (canon lower (func 0)))
   (core instance (;0;)
@@ -40,7 +41,6 @@
     )
   )
   (alias core export 1 "memory" (core memory (;0;)))
-  (type (;3;) (record (field "f" u8)))
   (type (;4;) (func (result 3)))
   (alias core export 1 "foo:foo/i#the-func" (core func (;1;)))
   (alias core export 1 "cabi_realloc" (core func (;2;)))
diff --git a/tests/cli/dummy-async-export-using-export.wit b/tests/cli/dummy-async-export-using-export.wit
new file mode 100644
index 00000000..1f95eaf5
--- /dev/null
+++ b/tests/cli/dummy-async-export-using-export.wit
@@ -0,0 +1,18 @@
+// RUN: component embed % --dummy-names legacy --async-callback | \
+//        component new | \
+//        validate -f component-model-async
+
+package a:b;
+
+interface a {
+  type a = s32;
+}
+
+world w {
+  export a;
+
+  export b: interface {
+    use a.{a};
+    d: func() -> a;
+  }
+}
diff --git a/tests/local/missing-features/function-references/hint.wast b/tests/local/missing-features/function-references/hint.wast
new file mode 100644
index 00000000..74b15d1a
--- /dev/null
+++ b/tests/local/missing-features/function-references/hint.wast
@@ -0,0 +1,5 @@
+(assert_invalid
+  (module
+    (type $ty (func (param (ref null $ty))))
+  )
+  "unknown type 0: type index out of bounds because the GC proposal is disabled")
diff --git a/tests/snapshots/local/missing-features/function-references/hint.wast.json b/tests/snapshots/local/missing-features/function-references/hint.wast.json
new file mode 100644
index 00000000..50b16244
--- /dev/null
+++ b/tests/snapshots/local/missing-features/function-references/hint.wast.json
@@ -0,0 +1,12 @@
+{
+  "source_filename": "tests/local/missing-features/function-references/hint.wast",
+  "commands": [
+    {
+      "type": "assert_invalid",
+      "line": 2,
+      "filename": "hint.0.wasm",
+      "module_type": "binary",
+      "text": "unknown type 0: type index out of bounds because the GC proposal is disabled"
+    }
+  ]
+}
\ No newline at end of file