[Media] skerry: Experimenting with per function errors with easy conversions, replacing monolithic error enums and opaque errors.

84 points Zkojin 13 comments
[Media] skerry: Experimenting with per function errors with easy conversions, replacing monolithic error enums and opaque errors.

Crate: https://crates.io/crates/skerry

I started this project because while I love error handling in rust the fact that I either have to match against 200 errors when only 2 are actually possible or manually write one billion enums and the conversions between them is incredibly annoying. Of course opaque errors like anyhow kind of work but then handling errors becomes extremely annoying.

The goal of skerry is to allow those fine grained enum matching with as little boilerplate as possible, I even plan on the future to add a module wide macro that would remove the need for all the #[] annotations.

Pros:

  • Your match statements only ever contain the variants that the function can actually return.

  • You instantly get an error through analyzer if the type you're converting from is not a subset to your function error.

  • The * prefix can flatten errors for you so matching is extremely easy

  • You don't really need to generate one error per function, if 2 functions return the exact same error you can do the following and it won't add any new types:

    define_error!(ManualDefine, [ErrorA, ErrorB]);

    [skerry_fn]
    fn my_fn1() -> Result<(), ManualDefine> { //... }
    [skerry_fn]
    fn my_fn2() -> Result<(), ManualDefine> { //... }

Cons:

  • It really polutes the namespace with a bunch of error types, and at least in it's current state they're not contained inside a separate module, there are plans to at least mitigate this.
  • It can get pretty annoying if your lib uses skerry as the end users would have to first convert to the global error type generated that contains all variants to only then return, otherwise they would need to write a From to their errors for every single function. There are plans to add a optional feature that would automatically convert all errors into one global huge enum, you could then add this feature as an optional feature on your project and allow end users to choose.
  • Currently the generated types don't handle Clone, Debug or anything else than error conversion, you can manually implement them if you want though.

Overall if you're curious please check the docs, I've only been working on this project for short time so expect problems. Can't talk about build times, but all these macros do is implement 2 impl From blocks and a bunch of of marker traits (1 per error type your error doesn't use, if we had negative traits this would be the opposite, 1 per error type you use).