From dc86fbafee0a5180615d4e726a61351887a8e79f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 19 Sep 2025 18:38:29 -0700 Subject: [PATCH] Fix a panic componentizing a library with `task.return` This commit fixes a mistake within `wit-component` where the wrong metadata map was used to lookup the string encoding to use for the `task.return` intrinsic. Previously a panic was generated as the wrong map was used. --- crates/wit-component/src/encoding.rs | 2 +- .../custom-page-sizes/component.wat | 2 +- .../link-lib-with-async-export/component.wat | 144 ++++++++++++++++++ .../component.wit.print | 19 +++ .../link-lib-with-async-export/lib-c.wat | 4 + .../link-lib-with-async-export/lib-c.wit | 3 + .../link-lib-with-async-export/lib-foo.wat | 12 ++ .../link-lib-with-async-export/lib-foo.wit | 16 ++ 8 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 crates/wit-component/tests/components/link-lib-with-async-export/component.wat create mode 100644 crates/wit-component/tests/components/link-lib-with-async-export/component.wit.print create mode 100644 crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wat create mode 100644 crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wit create mode 100644 crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wat create mode 100644 crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wit diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs index ad0f8a1c1e..8ec301cda0 100644 --- a/crates/wit-component/src/encoding.rs +++ b/crates/wit-component/src/encoding.rs @@ -1786,7 +1786,7 @@ impl<'a> EncodingState<'a> { let index = self.component.task_return(result, []); Ok((ExportKind::Func, index)) } else { - let metadata = &self.info.encoder.metadata.metadata; + let metadata = &self.info.module_metadata_for(for_module); let encoding = metadata.export_encodings.get(resolve, key, func).unwrap(); Ok(self.materialize_shim_import( shims, diff --git a/crates/wit-component/tests/components/custom-page-sizes/component.wat b/crates/wit-component/tests/components/custom-page-sizes/component.wat index 99864d6e30..a58ca3bf01 100644 --- a/crates/wit-component/tests/components/custom-page-sizes/component.wat +++ b/crates/wit-component/tests/components/custom-page-sizes/component.wat @@ -20,4 +20,4 @@ (@producers (processed-by "wit-component" "$CARGO_PKG_VERSION") ) -) \ No newline at end of file +) diff --git a/crates/wit-component/tests/components/link-lib-with-async-export/component.wat b/crates/wit-component/tests/components/link-lib-with-async-export/component.wat new file mode 100644 index 0000000000..2ac086f7a7 --- /dev/null +++ b/crates/wit-component/tests/components/link-lib-with-async-export/component.wat @@ -0,0 +1,144 @@ +(component + (type (;0;) (record (field "a1" string) (field "a2" string) (field "a3" string) (field "a4" string))) + (import "big2" (type $big2 (;1;) (eq 0))) + (type (;2;) (record (field "a1" $big2) (field "a2" $big2) (field "a3" $big2) (field "a4" $big2))) + (import "big" (type $big (;3;) (eq 2))) + (core module $main (;0;) + (type (;0;) (func)) + (table (;0;) 2 funcref) + (memory (;0;) 17) + (global (;0;) (mut i32) i32.const 1048576) + (global (;1;) i32 i32.const 1048592) + (global (;2;) i32 i32.const 1) + (global (;3;) i32 i32.const 1048592) + (global (;4;) i32 i32.const 1) + (global (;5;) (mut i32) i32.const 1048608) + (global (;6;) (mut i32) i32.const 1114112) + (export "__stack_pointer" (global 0)) + (export "c:memory_base" (global 1)) + (export "c:table_base" (global 2)) + (export "foo:memory_base" (global 3)) + (export "foo:table_base" (global 4)) + (export "__heap_base" (global 5)) + (export "__heap_end" (global 6)) + (export "foo" (func 0)) + (export "__indirect_function_table" (table 0)) + (export "memory" (memory 0)) + (func (;0;) (type 0) + i32.const 1 + call_indirect (type 0) + ) + (@producers + (processed-by "wit-component" "$CARGO_PKG_VERSION") + ) + ) + (core module $c (;1;) + (@dylink.0 + (mem-info (memory 0 4)) + ) + (type (;0;) (func)) + (import "env" "foo" (func (;0;) (type 0))) + ) + (core module $foo (;2;) + (@dylink.0 + (mem-info (memory 4 4)) + (needed "c") + ) + (type (;0;) (func (param i32))) + (type (;1;) (func)) + (type (;2;) (func (result i32))) + (type (;3;) (func (param i32 i32 i32) (result i32))) + (import "[export]$root" "[task-return][async]f" (func (;0;) (type 0))) + (export "foo" (func 1)) + (export "[async-lift][async]f" (func 2)) + (export "[callback][async-lift][async]f" (func 3)) + (func (;1;) (type 1)) + (func (;2;) (type 2) (result i32) + unreachable + ) + (func (;3;) (type 3) (param i32 i32 i32) (result i32) + unreachable + ) + ) + (core module $__init (;3;) + (type (;0;) (func)) + (type (;1;) (func (param i32))) + (type (;2;) (func)) + (import "env" "memory" (memory (;0;) 0)) + (import "env" "__indirect_function_table" (table (;0;) 0 funcref)) + (import "foo" "foo" (func (;0;) (type 2))) + (start 1) + (elem (;0;) (i32.const 1) func) + (elem (;1;) (i32.const 1) func 0) + (func (;1;) (type 0)) + (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00") + (@producers + (processed-by "wit-component" "$CARGO_PKG_VERSION") + ) + ) + (core module $wit-component-shim-module (;4;) + (type (;0;) (func (param i32))) + (table (;0;) 1 1 funcref) + (export "0" (func $"task-return-[async]f")) + (export "$imports" (table 0)) + (func $"task-return-[async]f" (;0;) (type 0) (param i32) + local.get 0 + i32.const 0 + call_indirect (type 0) + ) + (@producers + (processed-by "wit-component" "$CARGO_PKG_VERSION") + ) + ) + (core module $wit-component-fixup (;5;) + (type (;0;) (func (param i32))) + (import "" "0" (func (;0;) (type 0))) + (import "" "$imports" (table (;0;) 1 1 funcref)) + (elem (;0;) (i32.const 0) func 0) + (@producers + (processed-by "wit-component" "$CARGO_PKG_VERSION") + ) + ) + (core instance $wit-component-shim-instance (;0;) (instantiate $wit-component-shim-module)) + (core instance $main (;1;) (instantiate $main)) + (alias core export $main "memory" (core memory $memory (;0;))) + (alias core export $main "foo" (core func $foo (;0;))) + (core instance $env (;2;) + (export "foo" (func $foo)) + ) + (core instance $c (;3;) (instantiate $c + (with "env" (instance $env)) + ) + ) + (alias core export $wit-component-shim-instance "0" (core func $"task-return-[async]f" (;1;))) + (core instance $"[export]$root" (;4;) + (export "[task-return][async]f" (func $"task-return-[async]f")) + ) + (core instance $foo (;5;) (instantiate $foo + (with "[export]$root" (instance $"[export]$root")) + ) + ) + (alias core export $wit-component-shim-instance "$imports" (core table $"shim table" (;0;))) + (core func $task.return (;2;) (canon task.return (result $big) (memory $memory) string-encoding=utf8)) + (core instance $fixup-args (;6;) + (export "$imports" (table $"shim table")) + (export "0" (func $task.return)) + ) + (core instance $fixup (;7;) (instantiate $wit-component-fixup + (with "" (instance $fixup-args)) + ) + ) + (core instance $__init (;8;) (instantiate $__init + (with "env" (instance $main)) + (with "foo" (instance $foo)) + ) + ) + (type (;4;) (func (result $big))) + (alias core export $foo "[async-lift][async]f" (core func $"[async-lift][async]f" (;3;))) + (alias core export $foo "[callback][async-lift][async]f" (core func $"[callback][async-lift][async]f" (;4;))) + (func $"[async]f" (;0;) (type 4) (canon lift (core func $"[async-lift][async]f") (memory $memory) string-encoding=utf8 async (callback $"[callback][async-lift][async]f"))) + (export $"#func1 [async]f" (@name "[async]f") (;1;) "[async]f" (func $"[async]f")) + (@producers + (processed-by "wit-component" "$CARGO_PKG_VERSION") + ) +) diff --git a/crates/wit-component/tests/components/link-lib-with-async-export/component.wit.print b/crates/wit-component/tests/components/link-lib-with-async-export/component.wit.print new file mode 100644 index 0000000000..bd41ab6a87 --- /dev/null +++ b/crates/wit-component/tests/components/link-lib-with-async-export/component.wit.print @@ -0,0 +1,19 @@ +package root:component; + +world root { + record big2 { + a1: string, + a2: string, + a3: string, + a4: string, + } + + record big { + a1: big2, + a2: big2, + a3: big2, + a4: big2, + } + + export f: async func() -> big; +} diff --git a/crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wat b/crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wat new file mode 100644 index 0000000000..4115794a7a --- /dev/null +++ b/crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wat @@ -0,0 +1,4 @@ +(module + (@dylink.0 (mem-info (memory 0 4))) + (import "env" "foo" (func)) +) diff --git a/crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wit b/crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wit new file mode 100644 index 0000000000..262c853de3 --- /dev/null +++ b/crates/wit-component/tests/components/link-lib-with-async-export/lib-c.wit @@ -0,0 +1,3 @@ +package test:test; + +world lib-c { } diff --git a/crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wat b/crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wat new file mode 100644 index 0000000000..e11681efc8 --- /dev/null +++ b/crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wat @@ -0,0 +1,12 @@ +(module + (@dylink.0 + (mem-info (memory 4 4)) + (needed "c") + ) + + (import "[export]$root" "[task-return][async]f" (func (param i32))) + + (func (export "foo")) + (func (export "[async-lift][async]f") (result i32) unreachable) + (func (export "[callback][async-lift][async]f") (param i32 i32 i32) (result i32) unreachable) +) diff --git a/crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wit b/crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wit new file mode 100644 index 0000000000..212e643c66 --- /dev/null +++ b/crates/wit-component/tests/components/link-lib-with-async-export/lib-foo.wit @@ -0,0 +1,16 @@ +package test:test; +world lib-foo { + record big { + a1: big2, + a2: big2, + a3: big2, + a4: big2, + } + record big2 { + a1: string, + a2: string, + a3: string, + a4: string, + } + export f: async func() -> big; +}