Support Result<T, E> as return type in #[func]#1544
Conversation
|
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-1544 |
|
This is great! Would it be possible to support |
|
Why not have an anyhow-style error type to which all error types can be coerced to? Bevy employs a similar approach using a universal error type called If gdext adopts this approach, users can write their fallible functions like this: #[func]
fn do_fallible_work(&self) -> Result<(), GodotError> {
let a: Result<(), FooError> = do_a();
a?;
let b: Result<(), BarError> = do_b();
b?;
let c: Result<(), BazError> = do_c();
c?;
Ok(())
}Similar to anyhow, Bevy also provides a type alias as an ergonomic enhancement: pub type Result<T = (), E = BevyError> = Result<T, E>;Applied to gdext, this makes it so that users can write their function signatures like this: #[func]
fn do_fallible_work_a(&self) -> Result {
// ...
Ok(())
}
#[func]
fn do_fallible_work_b(&self) -> Result<u32> {
// ...
Ok(5)
} |
|
@ogapo and @musjj very good ideas, thanks! I initially planned to not introduce too broad conversions, but maybe I overestimated their complexity... I'll definitely check how this would look 👍 I guess such error types would still map to the "fatal" path, i.e. GDScript sees Maybe we can then also start without |
|
Yeah mapping it to the fatal path sounds reasonable for now! In the future, maybe an option to register global/per-function error handlers (relevant?) could be added. A nice use case for this is creating a global error handler that panics in debug builds, but only logs a warning in release builds. |
|
This came up on Reddit as well 🙂 so yes, something to consider! |
f2bc9c7 to
8a3f1fd
Compare
|
I added the Updated PR description with a usage example. |
8a3f1fd to
97bd77e
Compare
97bd77e to
eb49408
Compare
c6826c4 to
9480105
Compare
|
I renamed the "fatal" error strategy to There are now two more possible types
I proposed a few other strategies ( Future work may include configuring hooks occurring during errors (linking this feature to #411). |
ee0ae0c to
ec49994
Compare
3c3fd56 to
d760781
Compare
Adds `ErrorToGodot` trait to customize error mapping strategies. Supports a few common ones out of the box.
d760781 to
3e39db8
Compare
Closes #425.
Result<T, E>can now be returned to Godot. The representation on Godot's side depends onEand can be tweaked with anErrorToGodottrait.For now, only a few
Etypes are directly supported:Result<T, Unexpected>is converted asTto Godot. In the error case, the function call will print a Godot error. The calling code will either abort the function (in GDScript with varcall and Godot Debug builds) or receive a default value.Result<T, ()>returns aVariantwhich is eitherT::to_variant()or nil.Result<(), global::Error>returns theglobal::Errorenum.You could customize this with your own
Etypes:Result<T, MyGodotResult>could return a custom class that requires checking for errors before accessing the value.Result<Array<T>, MyGenericArray>could emulate anOption<T>like type in Godot:[]on error,[T]on success. Typed but no error value.Example usage:
I'd like to keep this PR limited in scope, we can add more building blocks for common errors later. But it's important that we get the foundation somewhat right.
One thing that's not too nice is that some impls need an extra bound
ToGodot<Via: Clone>. I should have madeGodotConvert::Via: Clonean implied bound, but now that needs to wait until v0.6. Unless I add it directly onGodotType... 🧐 Edit: solved in #1545