Skip to content

Allow constructors to be fallible #550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions design/mvp/Binary.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,9 @@ Notes:
`[static]` matches the `plainname` of a preceding `resource` import or
export, respectively, in the same scope (component, component type or
instance type).
* Validation of `[constructor]` names requires that the `func` returns a
`(result (own $R))`, where `$R` is the resource labeled `r`.
* Validation of `[constructor]` names requires a `func` type whose result type
is either `(own $R)` or `(result (own $R) E?)` where `$R` is a resource type
labeled `r`.
* Validation of `[method]` names requires the first parameter of the function
to be `(param "self" (borrow $R))`, where `$R` is the resource labeled `r`.
* 🔗 Validation requires that `versionsuffix` is preceded by an `interfaceversion`
Expand Down
16 changes: 13 additions & 3 deletions design/mvp/Explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2454,9 +2454,19 @@ generators to insert the function into the nested scope of a class, abstract
data type, object, namespace, package, module or whatever resources get bound
to. For example, a function named `[method]C.foo` could be bound in C++ to a
member function `foo` in a class `C`. The JS API [below](#JS-API) describes how
the native JavaScript bindings could look. Validation described in
[Binary.md](Binary.md) inspects the contents of `plainname` and ensures that
the function has a compatible signature.
the native JavaScript bindings could look.

To restrict the set of cases that bindings generators need to consider, these
annotations trigger additional type-validation rules (listed in
[Binary.md](Binary.md)) such as:
* An import or export named `[static]R.foo` must be a function and `R` must
be the name of an imported or exported resource type in the same `instance`
or `component` type.
* Similarly, an import or export named `[constructor]R` must be a function
whose return type must be `(own $R)` or `(result (own $R) (error <valtype>)?)`
where `$R` is the type-index of the resource type named `R`.
* Similarly, an import or export named `[method]R.foo` must be a function whose
first parameter must be `(param "self" (borrow $R))`.

When a function is annotated with `async`, bindings generators are expected to
emit whatever asynchronous language construct is appropriate (such as an
Expand Down
8 changes: 8 additions & 0 deletions design/mvp/WIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,10 @@ functions*, which do not have an implicit `self` parameter but are meant to be
lexically nested in the scope of the resource type. Lastly, a resource
statement can contain at most one *constructor* function, which is syntactic
sugar for a function returning a handle of the containing resource type.
Constructors can be fallible or infallible. Fallible constructors have an
explicitly-written return type which must be of the form `result<r, ...>`
where `r` is the name of the containing `resource`. Infallible constructors
have no written return type and are given the implicit return type `r`.

For example, the following resource definition:
```wit
Expand All @@ -1650,11 +1654,15 @@ resource blob {
read: func(n: u32) -> list<u8>;
merge: static func(lhs: borrow<blob>, rhs: borrow<blob>) -> blob;
}
resource blob2 {
constructor(init: list<u8>) -> result<blob2>;
}
```
desugars into:
```wit
resource blob;
%[constructor]blob: func(init: list<u8>) -> blob;
%[constructor]blob2: func(init: list<u8>) -> result<blob2>;
%[method]blob.write: func(self: borrow<blob>, bytes: list<u8>);
%[method]blob.read: func(self: borrow<blob>, n: u32) -> list<u8>;
%[static]blob.merge: func(lhs: borrow<blob>, rhs: borrow<blob>) -> blob;
Expand Down