Skip to content

Commit fd0b9e2

Browse files
authored
Allow constructors to be fallible (#550)
1 parent 6c5537d commit fd0b9e2

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

design/mvp/Binary.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,9 @@ Notes:
401401
`[static]` matches the `plainname` of a preceding `resource` import or
402402
export, respectively, in the same scope (component, component type or
403403
instance type).
404-
* Validation of `[constructor]` names requires that the `func` returns a
405-
`(result (own $R))`, where `$R` is the resource labeled `r`.
404+
* Validation of `[constructor]` names requires a `func` type whose result type
405+
is either `(own $R)` or `(result (own $R) E?)` where `$R` is a resource type
406+
labeled `r`.
406407
* Validation of `[method]` names requires the first parameter of the function
407408
to be `(param "self" (borrow $R))`, where `$R` is the resource labeled `r`.
408409
* 🔗 Validation requires that `versionsuffix` is preceded by an `interfaceversion`

design/mvp/Explainer.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2454,9 +2454,19 @@ generators to insert the function into the nested scope of a class, abstract
24542454
data type, object, namespace, package, module or whatever resources get bound
24552455
to. For example, a function named `[method]C.foo` could be bound in C++ to a
24562456
member function `foo` in a class `C`. The JS API [below](#JS-API) describes how
2457-
the native JavaScript bindings could look. Validation described in
2458-
[Binary.md](Binary.md) inspects the contents of `plainname` and ensures that
2459-
the function has a compatible signature.
2457+
the native JavaScript bindings could look.
2458+
2459+
To restrict the set of cases that bindings generators need to consider, these
2460+
annotations trigger additional type-validation rules (listed in
2461+
[Binary.md](Binary.md)) such as:
2462+
* An import or export named `[static]R.foo` must be a function and `R` must
2463+
be the name of an imported or exported resource type in the same `instance`
2464+
or `component` type.
2465+
* Similarly, an import or export named `[constructor]R` must be a function
2466+
whose return type must be `(own $R)` or `(result (own $R) (error <valtype>)?)`
2467+
where `$R` is the type-index of the resource type named `R`.
2468+
* Similarly, an import or export named `[method]R.foo` must be a function whose
2469+
first parameter must be `(param "self" (borrow $R))`.
24602470

24612471
When a function is annotated with `async`, bindings generators are expected to
24622472
emit whatever asynchronous language construct is appropriate (such as an

design/mvp/WIT.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,10 @@ functions*, which do not have an implicit `self` parameter but are meant to be
16411641
lexically nested in the scope of the resource type. Lastly, a resource
16421642
statement can contain at most one *constructor* function, which is syntactic
16431643
sugar for a function returning a handle of the containing resource type.
1644+
Constructors can be fallible or infallible. Fallible constructors have an
1645+
explicitly-written return type which must be of the form `result<r, ...>`
1646+
where `r` is the name of the containing `resource`. Infallible constructors
1647+
have no written return type and are given the implicit return type `r`.
16441648

16451649
For example, the following resource definition:
16461650
```wit
@@ -1650,11 +1654,15 @@ resource blob {
16501654
read: func(n: u32) -> list<u8>;
16511655
merge: static func(lhs: borrow<blob>, rhs: borrow<blob>) -> blob;
16521656
}
1657+
resource blob2 {
1658+
constructor(init: list<u8>) -> result<blob2>;
1659+
}
16531660
```
16541661
desugars into:
16551662
```wit
16561663
resource blob;
16571664
%[constructor]blob: func(init: list<u8>) -> blob;
1665+
%[constructor]blob2: func(init: list<u8>) -> result<blob2>;
16581666
%[method]blob.write: func(self: borrow<blob>, bytes: list<u8>);
16591667
%[method]blob.read: func(self: borrow<blob>, n: u32) -> list<u8>;
16601668
%[static]blob.merge: func(lhs: borrow<blob>, rhs: borrow<blob>) -> blob;

0 commit comments

Comments
 (0)