GFUITBG5JGUCDMG34FEMPPJAZGQKURXA5L2RYS6YOQC4DIQGASMAC
N7U2FHPRHGARPZ6M7LYBDJ52NMYE23VD5YALZ7CC76W3V5OLBP7QC
LNM226ITXRMWOSX6GOJ4HO72BWFRBDKQTEZMF4QUJUACUIOKIEJQC
FUJQNVMLSYHOFH6Z663M2MIGQXYSWGMNUKEIT2O4JYER3CGGLV3AC
EKYR4HDT6DHI7H5YMSHEBHXLPDCA2X2XNXYHDKHWGMPHNVTUBCMQC
TOB3GIX6URUWT7SYBP4QJ5FWF6DKP3NMZXRWBZ3H7PKBAJ6VR2IQC
EW76CAD5Y3JX7PYTVSZZQDIOQBYM73ZLNTZUGTR6U7APLGCKX5BAC
KU3EUQE2P5B6JDOKOCOHMYLFGQMYTWIFXRKQCV4YHY26EIZQQ5VAC
7CFCRKLZLAJ6KKLMCMVKA54FPLPDEIQJWAJMYOESVAFIYYD24ZNQC
J5MV4B4AM4DQCWXQ6ZP4GSB3LDAXISZMKI6TIPI43CQRITKOY6DQC
236GOKPH456B2MQDNF63EHVYXOEWO26TGORKVYQZBT4LTIJFXPCAC
KVJLO32PLCESEZT2IHB467L6CN6EJBQ3FQY2MD53HDE46NAQWE7AC
TGRYO7YUCIFDN7I2FK5RXGTC7GZLLQVE7YYG7HYLK2Y7Q7C37TSAC
G2VYAJCVORVVN2ZLYRIIHZ5NE34BCCKC4GAK6GO4THUCMFH3I5GAC
U6V2B33XDTYWTEBLU6EXBUJ6MYKTCWYR67YAJUQ4ZG6FWLWXKZTQC
PZ7MJFBMS4GG34VVVCCTJ5TTEDEPFVL72CFRYBMOKRF2BC2FWQKQC
YJUQPNYMVFV46BIEXKJTRVXLSXSKBW23QON2SAP5PMQN5UVRB7ZAC
MCDKSHTMINAAHTISNB6UQPZSSGDI2OEHTHRXEK3Q6YP3SWREKZXAC
V2JI47ZPBHNQHEY4SAB5IE5NUBUUNN4DRTVECBG3S66VVUAMXT3QC
D65N7FFF6MOQ6CFSBVVDRC5VKPHNEEWIYXHT5UBLOWLJGPSYFA4AC
GL2F5JA26IICALTT4SQ56GI3W6J7M64XNW7HNAC2Y7ASRU6WNV2QC
VMNH3BH3MUBCODGOXU3JUFYLVKKKXQLGW7O73T6T45G276XNXSSQC
F6BP6K2WEKNTEBJGJH4LE2JXH3SDSO4GZFIK2J4EBC2PMGAKIKZAC
USP4ZMOPFNQT735CCLW3RYPOQUFHUQEAH7HNTVQEBXQVUZIQUUEQC
QLZQ4EFM22GEFD4JAXGL5O2DPIS5QXICOBIBWAQZMWULYAXLW3ZAC
QDAWHJQA5USW53TYHBRZ7NOWPRZ7LBWC7XLCNUCSRTQHJ22263WQC
UWMRLBK2V2EYFZVJ5ECX2BQAXDNPRJPYVBHYMJBNKG2PSCFPTXVAC
27FJCOHTEFRJBL5NVKLRYWYAOU6CI4U322PKFY72MRPV4UOWHK4QC
YNQFROO7XUHL53EEKSEO47FWWCWSBFN6YB4WXMFVVEOQUMF6DQRAC
JFNBM5AK6APNNL53OI7ZMCISM5Z4HXBLCXIJY7PQAEFUDHLE4HCAC
7QQNJET43BO52L6BB7GIIWWSD7YSZF56AKUNBEMY53KXL64EF5CAC
DM6P3O3COJK7GKPZHLFGEBOTOPDQMTWOAY2Q74R7O6YN4I7PD3EAC
Q7MCJVD4Y227MJCVURE67PLM5EAHJ3NHPL2JPJDXBIBPGV5C3F2AC
VPMZ53P77PEBGYXR46WL2XLD5IS4IJ545BZAKXE63OD2G5VJ5Y4QC
MCPTFJMN333Z2GVL5J2KPLR6BJ3TAZKUGFORXNZ4YZBRXVQLCMFQC
DBYTNFJIVBGNURGIPWS3NJBI4XPF6IU6NY2BLBTJCECYVCGBWSNAC
YWW5TKMSPEGRZ52FQZ3SC4C3DEZ57U5XUO4LHZC34BJA7QR5NSCQC
D3IJE5IHSC64GMC3QZUYMSPZL2PXIVOHCWF7BREKRQXJQLURZBLQC
6BNRWGF55J5M3YBWYNTWJCRJQSEHY7YRKOUBV43W7I2HCTFDJHUQC
CITEDKPB6MKVZUEYEDE5ZKTNVY35HCOAXKDPYG7YLLEOVFNMSRXQC
OXKWHQFHTDDOWX3QDMHDWHCT3HFKWQS7Z7DEL3ILJBA7GNITA4GAC
ZDN7BJ3JA3VL4AYWX3SV24GHP6NCAETJVAKAXKMIZTLHTWLUNMOQC
3ZZ75E2AOF7DO3TMR422QV7ZXNYOQZTOGF67LVSCEMX6N75Y36LAC
version = "1.0.26" # remember to update html_root_url
authors = ["David Tolnay <dtolnay@gmail.com>"]
version = "0.2.0" # remember to update html_root_url
authors = ["David Tolnay <dtolnay@gmail.com>", "Jane Lusby <jlusby42@gmail.com>"]
description = "Flexible concrete Error type built on std::error::Error"
repository = "https://github.com/dtolnay/eyre"
description = "Flexible concrete Error Handling and Reporting type built on std::error::Error"
repository = "https://github.com/yaahc/eyre"
First and foremost, this crate is a fork of `anyhow` by @dtolnay. My goal in
writing this crate is to explore new directions of handling context and to
explore new ways to communicate the intended usage of this crate via changes to
the API.
The main changes this crate brings to anyhow are
* Addition of the [`eyre::EyreContext`] trait and a type parameter on the core error
handling type which users can use to insert custom forms of context into
their general error type.
* Rebranding the type as principally for error reporting, rather than
describing it as an error type in its own right. This type is not an error,
it contains errors that it masqerades as, and provides helpers for creating
new errors to wrap those errors and for displaying those chains of errors,
and the included context, to the end user. The goal is to make it obvious
that this type is meant to be used when the only way you expect to handle
errors is to print them.
* Changing the [`anyhow::Context`] trait to [`eyre::WrapErr`] to make it clear
that it is unrelated to the [`eyre::EyreContext`] and the context member, and
is only for inserting new errors into the chain of errors.
* Addition of a new `context` function on [`eyre::ErrReport`] to assist with
extracting members from the inner Context, which is used by
[`eyre::ErrReport`] to extract [`std::backtrace::Backtrace`]'s from generic
contexts types.
These changes were made in order to facilitate the usage of
[`tracing::SpanTrace`] with anyhow, which is a Backtrace-like type for
rendering custom defined runtime context.
**Note**: The way the `eyre!` macro works in practice differs from how
`anyhow!` works due to the addition of the generic type parameter. In anyhow
the following is valid.
```rust
let val = get_optional_val.ok_or_else(|| anyhow!("failed to get value)).unwrap();
```
Where as with `eyre!` this will fail due to being unable to infer the type for
the Context parameter. The solution to this problem, should you encounter it,
is to give the compiler a hint for what type it should be resolving to, either
via your return type or a type annotation.
```rust
// Will work fine
let val: ErrReport = get_optional_val.ok_or_else(|| eyre!("failed to get value)).unwrap();
```
## Customization
In order to insert your own custom context type you must first implement the
`eyre::EyreContext` trait for said type, which has four required methods.
* `fn default(error: &Error) -> Self` - For constructing default context while
allowing special case handling depending on the content of the error you're
wrapping.
This is essentially `Default::default` but more flexible, for example, the
`eyre::DefaultContext` type provide by this crate uses this to only capture a
`Backtrace` if the inner `Error` does not already have one.
```rust
fn default(error: &(dyn StdError + 'static)) -> Self {
let backtrace = backtrace_if_absent!(error);
Self { backtrace }
}
```
* `fn context_raw(&self, typeid TypeID) -> Option<&dyn Any>` - For extracting
arbitrary members from a context based on their type.
This method is like a flexible version of the `fn backtrace(&self)` method on
the `Error` trait. In the future we will likely support extracting `Backtrace`s
and `SpanTrace`s by default by relying on the implementation of `context_raw`
provided by the user.
Here is how the `eyre::DefaultContext` type uses this to return `Backtrace`s.
```rust
fn context_raw(&self, typeid: TypeId) -> Option<&dyn Any> {
if typeid == TypeId::of::<Backtrace>() {
self.backtrace.as_ref().map(|b| b as &dyn Any)
} else {
None
}
}
```
* `fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt Result`
it's companion `display` version. - For formatting the entire error chain and
the user provided context.
When overriding the context it no longer makes sense for `eyre::ErrReport` to
provide the `Display` and `Debug` implementations for the user, becase we
cannot predict what forms of context you will need to display along side your
chain of errors. Instead we forward the implementations of `Display` and
`Debug` to these methods on the inner `EyreContext` type.
This crate does provide a few helpers to assist in writing display
implementations, specifically the `Chain` type, for treating an error and its
sources like an iterator, and the `Indented` type, for indenting multi line
errors consistently without using heap allocations.
**Note**: best practices for printing errors suggest that `{}` should only
print the current error and none of its sources, and that the primary method of
displaying an error, its sources, and its context should be handled by the
`Debug` implementation, which is what is used to print errors that are returned
from `main`. For examples on how to implement this please refer to the
implementations of `display` and `debug` on `eyre::DefaultContext`
Once you've defined a custom Context type you can use it throughout your
application by defining a type alias.
```rust
type ErrReport = eyre::ErrReport<MyContext>;
// And optionally...
type Result<T, E = eyre::ErrReport<MyContext>> = core::result::Result<T, E>;
```
fn context_raw(&self, typid: TypeId) -> Option<&dyn Any> {
match typid {
t if t == TypeId::of::<Backtrace>() => self.backtrace.as_ref().map(|b| b as &dyn Any),
_ => None,
fn context_raw(&self, typeid: TypeId) -> Option<&dyn Any> {
if typeid == TypeId::of::<Backtrace>() {
self.backtrace.as_ref().map(|b| b as &dyn Any)
} else {
None