Resource constructor result typing
Resource types don't currently have the ability to define constructors as having custom result return error types.
For this reason, custom static constructors are likely usually preferable for resources since most constructor patterns with non-trivial arguments will want argument validation.
Would it make sense to consider result overloading only for resource constructors? I believe most languages should come with the ability to return an error from a resource constructor.
Great point and thanks for filing! This same issue came up in another context, with the same tentative conclusion, so agreed this is a good thing to add right after Preview 2. I think the change here is just to loosen the validation criteria for [constructor]-prefixed functions to additionally allow a return type of (result (own $R) (error T)) (for any T). With this, languages with new and exceptions can continue to have new call the constructor whereas other languages can emit the appropriate idiom for fallible constructors.
Static methods also return T instead of GuestT, so this workaround doesn't work:
interface foo {
resource bar {
fallible-ctor: static func() -> result<bar, string>
}
}
I think this might be better than allowing constructor to return result<>, because languages such as JS cannot emit fallible constructors, but can admit fallible static methods that return this(). This allows making the constructor private and serving what some languages would call a smart constructor over the wire.
Sorry, I didn't follow your point regarding static methods, T, GuestT, and what's wrong with the workaround you showed?
because languages such as JS cannot emit fallible constructors
IIUC, the current prototyped JS bindings for result return types is that the failure case corresponds to an exception (with the result's error payload stored as a field on the exception object) and the success case just returns the success payload value directly (no wrapped with anything). Given this, a fallible constructor should I think map just fine to (throwing) new.
Is there any update on this? I ran into a similar issue with a WIT interface for a resource that has a constructor that takes other resources and may fail.
I implemented import and export bindings for this component in Go but the best I can seem to do is return a ResourceNone (Rep 0) when the constructor fails and check this on the import side but I am unable to pass error information so the importer could log why it failed.
Seems like from above the workaround is to not use the built-in constructor but curious if this will change at some point.
I think everyone agrees this is a good idea and it's pretty easy to add to the spec and runtime (it just relaxes the validation predicate for [constructor] functions); mostly the work is just to generalize the bindings generators to be able to call and implement result-returning constructors. If anyone wants to work on this, please post here and I'm happy to write up the tiny spec PR. Otherwise, I think we'll naturally get to this after Preview 3 is released (perhaps along with getters/setters).
This just came up again in https://github.com/WebAssembly/wasi-sockets/issues/128
the work is just to generalize the bindings generators to be able to call and implement result-returning constructors. If anyone wants to work on this, please post here
I can take a stab at it. I assume what was said above (2 years ago) still holds today: in that the signature must either be constructor(...); or constructor(...) -> result<R,E>;
Awesome! I filed #550 for the spec PR.
I've got the proposed changes (https://github.com/WebAssembly/component-model/pull/550) working at:
-
wasm-tools: https://github.com/bytecodealliance/wasm-tools/compare/main...badeend:wasm-tools:fallible-constructors -
wit-bindgen: https://github.com/bytecodealliance/wit-bindgen/compare/main...badeend:wit-bindgen:fallible-constructors- I've updated the Rust generator.
- The C generator happened to work immediately, without further changes needed.
- I haven't touched the C++ & C# generators yet. Currently, these produce incorrect output.
-
wasmtime: https://github.com/bytecodealliance/wasmtime/compare/main...badeend:wasmtime:fallible-constructors-
wasmtime-wit-bindgenworked out of the box. All I've done here is add a codegen testcase. - As a proof-of-concept I've temporarily changed the
tcp/udp-socketresources from a staticcreatemethod to fallible constructor and all tests pass.
-
What should the next steps be?
Nice! I think it's reasonable to PR those to each repo now and I can do a release of wasm-tools once that's merge so the other two can merge
FYI, support for this has landed in wasm-tools, wit-bindgen & wasmtime
Thanks for all the work on this! Can we close this issue as resolved?
I'd say so, yes ✅