Skip to content

Commit 1450603

Browse files
committed
Add support for WIT fallible constructors
This implements: WebAssembly/component-model#550
1 parent c2fc211 commit 1450603

37 files changed

+626
-159
lines changed

crates/wasmparser/src/validator/component.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4410,8 +4410,9 @@ impl ComponentNameContext {
44104410
| ComponentNameKind::Dependency(_)
44114411
| ComponentNameKind::Hash(_) => {}
44124412

4413-
// Constructors must return `(own $resource)` and the `$resource`
4414-
// must be named within this context to match `rname`
4413+
// Constructors must return `(own $resource)` or
4414+
// `(result (own $Tresource))` and the `$resource` must be named
4415+
// within this context to match `rname`.
44154416
ComponentNameKind::Constructor(rname) => {
44164417
let ty = func()?;
44174418
let ty = match ty.result {
@@ -4422,12 +4423,22 @@ impl ComponentNameContext {
44224423
ComponentValType::Primitive(_) => None,
44234424
ComponentValType::Type(ty) => match &types[ty] {
44244425
ComponentDefinedType::Own(id) => Some(id),
4426+
ComponentDefinedType::Result {
4427+
ok: Some(ComponentValType::Type(ok)),
4428+
..
4429+
} => match &types[*ok] {
4430+
ComponentDefinedType::Own(id) => Some(id),
4431+
_ => None,
4432+
},
44254433
_ => None,
44264434
},
44274435
};
44284436
let resource = match resource {
44294437
Some(id) => id,
4430-
None => bail!(offset, "function should return `(own $T)`"),
4438+
None => bail!(
4439+
offset,
4440+
"function should return `(own $T)` or `(result (own $T))`"
4441+
),
44314442
};
44324443
self.validate_resource_name(*resource, rname, offset)?;
44334444
}

crates/wit-component/src/printing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,8 @@ impl<O: Output> WitPrinter<O> {
371371
}
372372
self.output.str(")");
373373

374-
// constructors don't have their results printed
375-
if let FunctionKind::Constructor(_) = func.kind {
374+
// shorthand constructors don't have their results printed
375+
if func.is_constructor_shorthand(resolve) {
376376
return Ok(());
377377
}
378378

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
(component
2+
(type (;0;)
3+
(instance
4+
(export (;0;) "a" (type (sub resource)))
5+
(type (;1;) (own 0))
6+
(type (;2;) (result 1 (error u32)))
7+
(type (;3;) (func (result 2)))
8+
(export (;0;) "[constructor]a" (func (type 3)))
9+
)
10+
)
11+
(import "foo" (instance (;0;) (type 0)))
12+
(core module (;0;)
13+
(type (;0;) (func (param i32)))
14+
(import "foo" "[constructor]a" (func (;0;) (type 0)))
15+
(import "foo" "[resource-drop]a" (func (;1;) (type 0)))
16+
(memory (;0;) 1)
17+
(export "memory" (memory 0))
18+
(@producers
19+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
20+
(processed-by "my-fake-bindgen" "123.45")
21+
)
22+
)
23+
(core module (;1;)
24+
(type (;0;) (func (param i32)))
25+
(table (;0;) 1 1 funcref)
26+
(export "0" (func $"indirect-foo-[constructor]a"))
27+
(export "$imports" (table 0))
28+
(func $"indirect-foo-[constructor]a" (;0;) (type 0) (param i32)
29+
local.get 0
30+
i32.const 0
31+
call_indirect (type 0)
32+
)
33+
(@producers
34+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
35+
)
36+
)
37+
(core module (;2;)
38+
(type (;0;) (func (param i32)))
39+
(import "" "0" (func (;0;) (type 0)))
40+
(import "" "$imports" (table (;0;) 1 1 funcref))
41+
(elem (;0;) (i32.const 0) func 0)
42+
(@producers
43+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
44+
)
45+
)
46+
(core instance (;0;) (instantiate 1))
47+
(alias core export 0 "0" (core func (;0;)))
48+
(alias export 0 "a" (type (;1;)))
49+
(core func (;1;) (canon resource.drop 1))
50+
(core instance (;1;)
51+
(export "[constructor]a" (func 0))
52+
(export "[resource-drop]a" (func 1))
53+
)
54+
(core instance (;2;) (instantiate 0
55+
(with "foo" (instance 1))
56+
)
57+
)
58+
(alias core export 2 "memory" (core memory (;0;)))
59+
(alias core export 0 "$imports" (core table (;0;)))
60+
(alias export 0 "[constructor]a" (func (;0;)))
61+
(core func (;2;) (canon lower (func 0) (memory 0)))
62+
(core instance (;3;)
63+
(export "$imports" (table 0))
64+
(export "0" (func 2))
65+
)
66+
(core instance (;4;) (instantiate 2
67+
(with "" (instance 3))
68+
)
69+
)
70+
(@producers
71+
(processed-by "wit-component" "$CARGO_PKG_VERSION")
72+
)
73+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package root:component;
2+
3+
world root {
4+
import foo: interface {
5+
resource a {
6+
constructor() -> result<a, u32>;
7+
}
8+
}
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(module
2+
(import "foo" "[constructor]a" (func (param i32)))
3+
(import "foo" "[resource-drop]a" (func (param i32)))
4+
(memory (export "memory") 1)
5+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package foo:bar;
2+
3+
world module {
4+
import foo: interface {
5+
resource a {
6+
constructor() -> result<a, u32>;
7+
}
8+
}
9+
}

crates/wit-component/tests/interfaces/resources.wat

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,18 @@
152152
(alias export 2 "bar" (type (;5;)))
153153
(import "bar" (type (;6;) (eq 5)))
154154
(import "a" (type (;7;) (sub resource)))
155-
(type (;8;) (own 7))
156-
(type (;9;) (func (result 8)))
157-
(import "[constructor]a" (func (;0;) (type 9)))
158-
(export (;1;) "x" (func (type 9)))
159-
(type (;10;) (own 6))
160-
(type (;11;) (func (result 10)))
161-
(export (;2;) "y" (func (type 11)))
155+
(import "b" (type (;8;) (sub resource)))
156+
(type (;9;) (own 7))
157+
(type (;10;) (func (result 9)))
158+
(import "[constructor]a" (func (;0;) (type 10)))
159+
(type (;11;) (own 8))
160+
(type (;12;) (result 11 (error string)))
161+
(type (;13;) (func (result 12)))
162+
(import "[constructor]b" (func (;1;) (type 13)))
163+
(export (;2;) "x" (func (type 10)))
164+
(type (;14;) (own 6))
165+
(type (;15;) (func (result 14)))
166+
(export (;3;) "y" (func (type 15)))
162167
)
163168
)
164169
(export (;0;) "foo:bar/some-world" (component (type 0)))

crates/wit-component/tests/interfaces/resources.wit

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ world some-world {
2727
constructor();
2828
}
2929

30+
resource b {
31+
constructor() -> result<b, string>;
32+
}
33+
3034
export x: func() -> a;
3135
export y: func() -> bar;
3236

crates/wit-component/tests/interfaces/resources.wit.print

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ world some-world {
6565
constructor();
6666
}
6767

68+
resource b {
69+
constructor() -> result<b, string>;
70+
}
71+
6872
export x: func() -> a;
6973
export y: func() -> bar;
7074
}

crates/wit-encoder/src/from_parser.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,6 @@ impl<'a> Converter<'a> {
397397
) -> Option<ResourceFunc> {
398398
// skip first argument for methods, as they're just `self`.
399399
let mut skip_first_param = false;
400-
// constructors can't return anything
401400
let mut with_returns = true;
402401
let mut method = match func.kind {
403402
wit_parser::FunctionKind::Freestanding
@@ -423,7 +422,7 @@ impl<'a> Converter<'a> {
423422
if id != resource_id {
424423
return None;
425424
}
426-
with_returns = false;
425+
with_returns = !func.is_constructor_shorthand(self.resolve);
427426
ResourceFunc::constructor()
428427
}
429428
};

0 commit comments

Comments
 (0)