Skip to content

Result systems #25

Closed
Closed
@cart

Description

@cart

The only way to handle errors in systems right now is to result.unwrap() them. This is both less ergonomic and panic-ey. Ideally systems could optionally return an anyhow::Result<()>. It would also be great if developers could define their own error handlers. Maybe some devs want to print their errors whereas others want to panic.

I think there are two approaches we could adopt here:

  1. Adapt legion to support return types
  2. Add impls for system fns that return results and handle the Result inside of into_system()

I think option (2) is the least destructive / most friendly to upstream, but it means that only system fns can handle errors.

If this is implemented, it also makes sense to modify bevy libs to return error types instead of Options for common operations to improve erognomics.

fn some_system(a: Res<A>, b: Res<B>, x: Com<X>, y: Com<Y>) -> Result<()> {
  a.do_something_risky()?;
  // system logic here
  Ok(())
}

// inside into_system() impl for Fn(Res<A>, Com<X>) -> Result<()>
system_builder.with_resource::<ErrorHandler>()
// resources are (error_handler, a, b)
result = run_system(a, b, x, y);
error_handler.handle(result);

The biggest downside to implementing this I can think of is that this multiplies the number of system fn impls by 2 (which is already in the hundreds of impls). That would come at an estimated clean-compile time cost of 40 seconds on fast computers ... not ideal. The best way to mitigate that is to revert to non-flat system fn impls, which would then only require a single new impl:

Doing so would both remove the need for a macro for system fn impls and reduce clean compile times by 40 seconds (current) / 80 seconds (with Result impls). But its also not nearly as nice to look at / type

// pseudocode
impl IntoSystem for Fn(ResourceSet, View<'a>) -> Result<()> { /* impl here */ }

fn some_system((a, b): (Res<A>, Res<B>), (x, y): (Com<X>, Com<Y>)) -> Result<()> {
  a.do_something_risky()?;
  // system logic here
  Ok(())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-FeatureA new feature, making something new possible

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions