Skip to content

Commit 70394c5

Browse files
wit-component: fix async task.return options for export signatures (#2452)
* wit-component: add regression for task.return options from async params * wit-component: fix async task.return options for export signatures * wit-component: derive task.return options from export func
1 parent 76927bf commit 70394c5

7 files changed

Lines changed: 127 additions & 27 deletions

File tree

crates/wit-component/src/encoding.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl RequiredOptions {
203203
}
204204
if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
205205
ret |= RequiredOptions::ASYNC;
206-
ret |= task_return_options_and_type(resolve, func.result).0;
206+
ret |= task_return_options_and_type(resolve, func).0;
207207
}
208208
ret
209209
}
@@ -1791,8 +1791,9 @@ impl<'a> EncodingState<'a> {
17911791
AbiVariant::GuestImport,
17921792
)
17931793
}
1794-
Import::ExportedTaskReturn(key, interface, func, result) => {
1795-
let (options, _sig) = task_return_options_and_type(resolve, *result);
1794+
Import::ExportedTaskReturn(key, interface, func) => {
1795+
let (options, _sig) = task_return_options_and_type(resolve, func);
1796+
let result_ty = func.result;
17961797
if options.is_empty() {
17971798
// Note that an "import type encoder" is used here despite
17981799
// this being for an exported function if the `interface`
@@ -1805,22 +1806,25 @@ impl<'a> EncodingState<'a> {
18051806
self.root_export_type_encoder(*interface)
18061807
};
18071808

1808-
let result = match result {
1809+
let result = match result_ty.as_ref() {
18091810
Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
18101811
None => None,
18111812
};
18121813
let index = self.component.task_return(result, []);
18131814
Ok((ExportKind::Func, index))
18141815
} else {
18151816
let metadata = &self.info.module_metadata_for(for_module);
1816-
let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1817+
let encoding = metadata
1818+
.export_encodings
1819+
.get(resolve, key, &func.name)
1820+
.unwrap();
18171821
Ok(self.materialize_shim_import(
18181822
shims,
18191823
&ShimKind::TaskReturn {
18201824
for_module,
18211825
interface: *interface,
1822-
func,
1823-
result: *result,
1826+
func: &func.name,
1827+
result: result_ty,
18241828
encoding,
18251829
},
18261830
))
@@ -2638,16 +2642,16 @@ impl<'a> Shims<'a> {
26382642
// If `task.return` needs to be indirect then generate a shim
26392643
// for it, otherwise skip the shim and let it get materialized
26402644
// naturally later.
2641-
Import::ExportedTaskReturn(key, interface, func, ty) => {
2642-
let (options, sig) = task_return_options_and_type(resolve, *ty);
2645+
Import::ExportedTaskReturn(key, interface, func) => {
2646+
let (options, sig) = task_return_options_and_type(resolve, func);
26432647
if options.is_empty() {
26442648
continue;
26452649
}
26462650
let name = self.shims.len().to_string();
26472651
let encoding = world
26482652
.module_metadata_for(for_module)
26492653
.export_encodings
2650-
.get(resolve, key, func)
2654+
.get(resolve, key, &func.name)
26512655
.ok_or_else(|| {
26522656
anyhow::anyhow!(
26532657
"missing component metadata for export of \
@@ -2656,12 +2660,12 @@ impl<'a> Shims<'a> {
26562660
})?;
26572661
self.push(Shim {
26582662
name,
2659-
debug_name: format!("task-return-{func}"),
2663+
debug_name: format!("task-return-{}", func.name),
26602664
options,
26612665
kind: ShimKind::TaskReturn {
26622666
interface: *interface,
2663-
func,
2664-
result: *ty,
2667+
func: &func.name,
2668+
result: func.result,
26652669
for_module,
26662670
encoding,
26672671
},
@@ -3027,15 +3031,15 @@ impl<'a> Shims<'a> {
30273031

30283032
fn task_return_options_and_type(
30293033
resolve: &Resolve,
3030-
ty: Option<Type>,
3034+
func: &Function,
30313035
) -> (RequiredOptions, WasmSignature) {
30323036
let func_tmp = Function {
30333037
name: String::new(),
30343038
kind: FunctionKind::Freestanding,
3035-
params: match ty {
3039+
params: match &func.result {
30363040
Some(ty) => vec![Param {
30373041
name: "a".to_string(),
3038-
ty,
3042+
ty: *ty,
30393043
span: Default::default(),
30403044
}],
30413045
None => Vec::new(),
@@ -3046,7 +3050,9 @@ fn task_return_options_and_type(
30463050
span: Default::default(),
30473051
};
30483052
let abi = AbiVariant::GuestImport;
3049-
let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
3053+
let mut options = RequiredOptions::for_import(resolve, func, abi);
3054+
// `task.return` does not support a `realloc` canonical option.
3055+
options.remove(RequiredOptions::REALLOC);
30503056
let sig = resolve.wasm_signature(abi, &func_tmp);
30513057
(options, sig)
30523058
}

crates/wit-component/src/encoding/world.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,9 @@ impl<'a> ComponentWorld<'a> {
403403

404404
// The `task.return` intrinsic needs to be able to refer to the
405405
// type that is being returned.
406-
Import::ExportedTaskReturn(.., ty) => {
407-
if let Some(ty) = ty {
408-
live.add_type(resolve, ty);
406+
Import::ExportedTaskReturn(.., func) => {
407+
if let Some(ty) = func.result {
408+
live.add_type(resolve, &ty);
409409
}
410410
}
411411

crates/wit-component/src/validation.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ pub enum Import {
268268
/// As of this writing, only async-lifted exports use `task.return`, but the
269269
/// plan is to also support it for sync-lifted exports in the future as
270270
/// well.
271-
ExportedTaskReturn(WorldKey, Option<InterfaceId>, String, Option<Type>),
271+
ExportedTaskReturn(WorldKey, Option<InterfaceId>, Function),
272272

273273
/// A `canon task.cancel` intrinsic for an exported function.
274274
///
@@ -901,12 +901,7 @@ impl ImportMap {
901901
let key = key.unwrap_or_else(|| WorldKey::Name(name.to_string()));
902902
// TODO: should call `validate_func_sig` but would require
903903
// calculating the expected signature based of `func.result`.
904-
return Ok(Some(Import::ExportedTaskReturn(
905-
key,
906-
id,
907-
func.name.clone(),
908-
func.result,
909-
)));
904+
return Ok(Some(Import::ExportedTaskReturn(key, id, func.clone())));
910905
}
911906
if names.task_cancel(name) {
912907
let expected = FuncType::new([], []);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
(component
2+
(core module $main (;0;)
3+
(type (;0;) (func))
4+
(type (;1;) (func (param i32 i32) (result i32)))
5+
(type (;2;) (func (param i32 i32 i32) (result i32)))
6+
(type (;3;) (func (param i32 i32 i32 i32) (result i32)))
7+
(import "[export]$root" "[task-cancel]" (func (;0;) (type 0)))
8+
(import "[export]$root" "[task-return]foo" (func (;1;) (type 0)))
9+
(memory (;0;) 1)
10+
(export "[async-lift]foo" (func 2))
11+
(export "[callback][async-lift]foo" (func 3))
12+
(export "memory" (memory 0))
13+
(export "cabi_realloc" (func 4))
14+
(func (;2;) (type 1) (param i32 i32) (result i32)
15+
unreachable
16+
)
17+
(func (;3;) (type 2) (param i32 i32 i32) (result i32)
18+
unreachable
19+
)
20+
(func (;4;) (type 3) (param i32 i32 i32 i32) (result i32)
21+
unreachable
22+
)
23+
(@producers
24+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
25+
(processed-by "my-fake-bindgen" "123.45")
26+
)
27+
)
28+
(core module $wit-component-shim-module (;1;)
29+
(type (;0;) (func))
30+
(table (;0;) 1 1 funcref)
31+
(export "0" (func $task-return-foo))
32+
(export "$imports" (table 0))
33+
(func $task-return-foo (;0;) (type 0)
34+
i32.const 0
35+
call_indirect (type 0)
36+
)
37+
(@producers
38+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
39+
)
40+
)
41+
(core module $wit-component-fixup (;2;)
42+
(type (;0;) (func))
43+
(import "" "0" (func (;0;) (type 0)))
44+
(import "" "$imports" (table (;0;) 1 1 funcref))
45+
(elem (;0;) (i32.const 0) func 0)
46+
(@producers
47+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
48+
)
49+
)
50+
(core instance $wit-component-shim-instance (;0;) (instantiate $wit-component-shim-module))
51+
(core func $task.cancel (;0;) (canon task.cancel))
52+
(alias core export $wit-component-shim-instance "0" (core func $task-return-foo (;1;)))
53+
(core instance $"[export]$root" (;1;)
54+
(export "[task-cancel]" (func $task.cancel))
55+
(export "[task-return]foo" (func $task-return-foo))
56+
)
57+
(core instance $main (;2;) (instantiate $main
58+
(with "[export]$root" (instance $"[export]$root"))
59+
)
60+
)
61+
(alias core export $main "memory" (core memory $memory (;0;)))
62+
(alias core export $wit-component-shim-instance "$imports" (core table $"shim table" (;0;)))
63+
(alias core export $main "cabi_realloc" (core func $realloc (;2;)))
64+
(core func $task.return (;3;) (canon task.return (memory $memory) string-encoding=utf8))
65+
(core instance $fixup-args (;3;)
66+
(export "$imports" (table $"shim table"))
67+
(export "0" (func $task.return))
68+
)
69+
(core instance $fixup (;4;) (instantiate $wit-component-fixup
70+
(with "" (instance $fixup-args))
71+
)
72+
)
73+
(type (;0;) (func (param "s" string)))
74+
(alias core export $main "[async-lift]foo" (core func $"[async-lift]foo" (;4;)))
75+
(alias core export $main "[callback][async-lift]foo" (core func $"[callback][async-lift]foo" (;5;)))
76+
(func $foo (;0;) (type 0) (canon lift (core func $"[async-lift]foo") (memory $memory) (realloc $realloc) string-encoding=utf8 async (callback $"[callback][async-lift]foo")))
77+
(export $"#func1 foo" (@name "foo") (;1;) "foo" (func $foo))
78+
(@producers
79+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
80+
)
81+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package root:component;
2+
3+
world root {
4+
export foo: func(s: string);
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(module
2+
(import "[export]$root" "[task-cancel]" (func))
3+
(import "[export]$root" "[task-return]foo" (func))
4+
(func (export "[async-lift]foo") (param i32 i32) (result i32) unreachable)
5+
(func (export "[callback][async-lift]foo") (param i32 i32 i32) (result i32) unreachable)
6+
(memory (export "memory") 1)
7+
(func (export "cabi_realloc") (param i32 i32 i32 i32) (result i32) unreachable)
8+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package foo:foo;
2+
3+
world module {
4+
export foo: func(s: string);
5+
}

0 commit comments

Comments
 (0)