-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Provider
API for context information on errors (and possibly other things)
#133
Conversation
fbeab64
to
5b10430
Compare
…her things) Add tests to provider Fix newline on Cargo.toml
5b10430
to
a6420da
Compare
@@ -110,6 +110,8 @@ | |||
// | |||
// TODO: replace library with https://github.com/rust-lang/project-error-handling/issues/3. | |||
|
|||
#![warn(clippy::pedantic, clippy::nursery)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for these as warnings. I don't think we should ever block on them, but it's good to get the visibility (provided folks are able to make sensible decisions about what to address/when, and can avoid the distraction of their likely omnipresence).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we block on any warning currently which is strictly not backwards compatible:
hash/.github/workflows/rust.yml
Line 154 in 1cfc2e7
cargo clippy --manifest-path ${{ matrix.directory }}/Cargo.toml --all --all-features -- -D warnings |
I have written this crate taking into account those warnings. Adding those to our current engine would be just noise. We even disabled some of the most annoying clippy lints, but as we proceed, we want to enable them again:
hash/packages/engine/src/lib.rs
Lines 22 to 35 in 1cfc2e7
#![allow( | |
clippy::borrowed_box, | |
clippy::wrong_self_convention, | |
clippy::diverging_sub_expression, | |
clippy::expect_fun_call, | |
clippy::large_enum_variant, | |
clippy::type_complexity, | |
clippy::module_inception, | |
clippy::new_ret_no_self, | |
clippy::unnecessary_cast, | |
clippy::enum_variant_names, | |
clippy::should_implement_trait, | |
clippy::mutex_atomic | |
)] |
41b62ba
to
637ccee
Compare
Thanks for the very deep review! |
🌟 What is the purpose of this PR?
Contains the
Provider
trait and accompanying API, which enable trait objects to provide data based on typed requests, an alternate form of runtime reflection.Currently, we use
thiserror
in hEngine, which just wraps every error in another error. Errors may (or may not) contain additional information on the cause or the context. It's very hard to track down the exact cause with all it's information (without huge, nestedmatch error
statements). It's even harder to add more general information like theLocation
, where the error/cause/context happened. We want to replace our error handling with a more generic approach like shown in #134.The provider API was proposed by the official error handling project of Rust (originally to move
Error
intocore
). This PR effectively reimplements the proposedProvider
, so we can use it until/if it's merged into the language, I only added a few tests (which should have a code coverage of 100%).🔗 Related links
Asana task
RFC for the provider API which would replace this library as soon as it has landed/implemented.
The project-error-handling tries to improves the error trait. In order to move the trait into
core
, an alternative solution to backtrace provisioning had to be found. This is, where the provider API comes from.Move
Error
trait into core rust-lang/project-error-handling#3🔍 What does this change?
Provider
and the associated APIs support generic, type-driven access to data, and a mechanismfor implementers to provide such data. The key parts of the interface are the
Provider
traitfor objects which can provide data, and the
request_by_type_tag
function for data from anobject which implements
Provider
. Note that end users should not call requestingrequest_by_type_tag
directly, it is a helper function for intermediate implementers to use toimplement a user-facing interface.
Typically, a data provider is a trait object of a trait which extends
Provider
. A user willrequest data from the trait object by specifying the type or a type tag (a type tag is a type
used only as a type parameter to identify the type which the user wants to receive).
We pointed out (at least) the following points for our error handling:
Looking at the dataflow of the provider API:
request_by_type_tag
request_by_type_tag
creates aRequisition
object and passes it toProvider::provide
Provider::provide
tries providing values ofdifferent types using
Requisition::provide_*
. If the type tag matches the type requested bythe user, it will be stored in the
Requisition
object.request_by_type_tag
unpacks theRequisition
object and returns any stored value to theuser.
All these steps happen in Error handling, not in Error generation, i.e. everything is independent of threads/async etc. (2. ✅). Obviously context information is passed. This can be everything from an error message, over backtraces or spantraces up to file/line/column, where the error occurred (1. ✅). Since all information can be encoded, the error handler can do what it wants with it. E.g. put it into a nice logging entry (3. ✅) or output it nicely to the console (4. ✅).
🛡 Tests