Implement Context for Error
- Dominant language
- Rust
- Stars
- 6.7k
- Forks
- 224
- PR merge metrics
- No merged PRs in 30d
Description
# Current State
`Error` does not implement `Context`. It has a `context` method, but no `with_context` method.
In the documentation for `Error::context`, it says
> The primary reason to use error.context(...) instead of result.context(...) via the Context trait would be if the context needs to depend on some data held by the underlying error:
and gives an example
```
pub fn parse(path: impl AsRef) -> Result {
let file = File::open(&path)?;
parse_impl(file).map_err(|error| {
let context = format!(
"only the first {} lines of {} are valid",
error.line, path.as_ref().display(),
);
anyhow::Error::new(error).context(context)
})
}
```
# Proposal
Would it be possible to implement `Context` for types implementing `std::error::Error`?
Here, instead of always outputting a `Result`, `context` and `with_context` would output the "anyhowed" version of `Self` (i.e., `anyhow::Error` for errors, `anyhow::Result` for result).
# Use Cases
1. There is the use case stated in the docs, where the context depends on the error. The example from the docs would then look like
```
pub fn parse(path: impl AsRef) -> Result {
let file = File::open(&path)?;
parse_impl(file).map_err(|error| {
let context = format!(
"only the first {} lines of {} are valid",
error.line, path.as_ref().display(),
);
error.context(context)
})
}
```
2. When handling errors that may map to `anyhow` errors _or_ to other types of errors.
For example, I use `anyhow` in conjunction with `thiserror` to model internal errors on libraries:
```
trait Doer {
fn Do(&self) -> Result<(), DoError>;
}
#[derive(thiserror::Error, Debug)]
enum DoError {
#[error("Some specific error that the client should react to.")]
SomeError,
#[error("Some other error that the client should react to.")]
OtherError,
#[error(transparent)]
Internal(#[from] anyhow::Error),
}
```
Sometimes I need to map an error from a dependency into _either_ a specific kind of an error, or an internal error with context. When this arises, I often use some sort of match, e.g.,
```
impl Doer for MyDoer {
fn Do(&self) -> Result<(), DoError> {
match self.fallible_dependency.call() {
Ok(_) => Ok(()),
Err(DependencyError::A) => Err(DoError::SomeError),
Err(DependencyError::B) => Err(DoError::OtherError),
Err(_) => Err(anyhow::Error::new(err).context("Some context.").into()),
}
}
}
```
It would be nice to be able to write this last arm as something like
```
Err(_) => Err(err.context("Some context.").into())
```
# Pros
1. This makes the cases above more readable.
2. It would be nice to have a unified way to add context to results or errors.
# Cons
1. This would complicate the `Context` trait. I can see this not being worth it just to avoid the `anyhow::Error::new` call.
2. `with_context` may not provide much value since you already know you're in the error case when adding context directly to an error so you don't need to avoid the overhead.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.