errors: replace anyhow with thiserror#212
Conversation
d6bf7cf to
76b50d3
Compare
fixes microsoft#161 This change replaces stringly-typed anyhow errors with thiserror-constructed explicit error enums. The following strategy has been used in the conversion: - Every module maintains its own error enum - Exception is builtins/*.rs in which all errors are consolidated in one enum to avoid duplication - Source errors are being wrapped and propagated in the error string - Crate-specific businesslogic errors have been convernted into their own enum - A simple `bail!` macro has been added to reduce changes - Extension fn's require a `Box<dyn std::error::Error>` error type. it would be nice if the Extension fn's could have a result with trait bound `std::error::Error` but that requires some unergonomic type gymnastics on the trait + impls - A local type alias for `Result` has been added to modules to reduce changes in the signatures where reasonable. Signed-off-by: Magnus Kulke <magnuskulke@microsoft.com>
76b50d3 to
23af0e4
Compare
|
Thanks for taking this on @mkulke. I have a few questions:
|
What would be the impact on a user of the library? The What would be the recommended way to notify the user of such breaking changes? Does cargo provide any way? |
src/engine.rs
Outdated
| #[error("value error: {0}")] | ||
| ValueError(#[from] ValueError), | ||
| #[error("data must be object")] | ||
| DataMustBeObject, |
There was a problem hiding this comment.
Say in a future version we refactor the code and eliminate the chance of such an error, would that be a breaking change?
There was a problem hiding this comment.
The enum can be marked #[non_exhaustive], but I'm not sure whether that's a good pattern. Ideally the types cover more or less what could go wrong in a given public fn call w/ a granularity that is useful to the consumer.
It's annoying if the error type is shared and there will be a new fn added to the API. Adding a new error case would be a breaking change. But maybe the types could be per-fn or logically grouped (like engine::EvalError)?
Say we later find out a better way to group and name errors, is there a way to make that a non-breaking change? |
At the moment the API exposes an |
yeah, if the error is marked as #[derive(Error, Debug)]
pub enum SchedulerError {
...
#[error(transparent)]
LexerError(#[from] LexerError),
...
}...and similarly for $ cargo run -r --example regorus -- eval "1+(a+b)"
Compiling regorus v0.1.5 (/home/magnuskulke/dev/regorus)
Finished release [optimized + debuginfo] target(s) in 13.08s
Running `target/release/examples/regorus eval '1+(a+b)'`
Error:
--> <query.rego>:1:4
|
1 | 1+(a+b)
| ^
error: use of undefined variable `a` is unsafe |
I think we probably want to think a bit which errors should be exposed as top-level API, which are useful for the consumer, so .e.g |
Cargo relies on semver, so if it's bumped to |
- Internal errors are merely propagated along the call stack now - engine::* errors have been split and grouped logically Signed-off-by: Magnus Kulke <magnuskulke@microsoft.com>
|
@mkulke
|
hey there @anakrish I took a stab at this one, PTAL. note: this would be breaking change.
fixes #161
This change replaces stringly-typed anyhow errors with thiserror-constructed explicit error enums.
The following strategy has been used in the conversion:
src/builtins/*.rsin which all errors are consolidated in a single enum to avoid duplicationbail!macro has been added to reduce changesBox<dyn std::error::Error>error type. it would be nice if the extension fn's could have a result with trait boundstd::error::Errorbut that requires some unergonomic type gymnastics on the trait + implsResulthas been added to modules to reduce changes in the signatures where reasonable.