MDCKAPJFOWFR5HBN3CU6ZGKYXP3QND5H5IV53ZKT34HPTR3YAEDAC KINDNEPN54H5ZHTPYMT7QX7JJEJ6TVQAK4O5YIFZWPKZH3D7455QC S3AZSHGCYIPPQLNJBYKHCQWFPKRHRE2VTAWKVAL3AOLNJZHQARRQC LNM226ITXRMWOSX6GOJ4HO72BWFRBDKQTEZMF4QUJUACUIOKIEJQC EKYR4HDT6DHI7H5YMSHEBHXLPDCA2X2XNXYHDKHWGMPHNVTUBCMQC GFUITBG5JGUCDMG34FEMPPJAZGQKURXA5L2RYS6YOQC4DIQGASMAC DBYTNFJIVBGNURGIPWS3NJBI4XPF6IU6NY2BLBTJCECYVCGBWSNAC MCPTFJMN333Z2GVL5J2KPLR6BJ3TAZKUGFORXNZ4YZBRXVQLCMFQC EBCOKP4HQSTNUXR5PJQUWTOQEE3DGB6W3KKIN5TYP4FPWAS5ORHQC TXHTORSMXMKDSGFNFIKQZYIY3KBDKJF2DJPA55NW4R6ZYBCQKRVQC YTH3GCSKUG34XBAAVP65UA67C26K2JDDL2N6PGYLKL2GG3MGFU6AC OQCFKTKCBTWGXL27ZLWQSL4L5VPREJAYN7MVCCR4GXW6WLWYOUHAC YWW5TKMSPEGRZ52FQZ3SC4C3DEZ57U5XUO4LHZC34BJA7QR5NSCQC OFA7R4NFSICEFZE2SLDK7IP3ZZH4MFWN2YIT756ZJ42W2QJHTOWQC FJ7MWHMLIDTBGJJNKCNS5GIBQIJBUQRXLQEAFOCVZI7O4NA4XGSAC 6BNRWGF55J5M3YBWYNTWJCRJQSEHY7YRKOUBV43W7I2HCTFDJHUQC GOPJFSDQLXOY7EGBNR26HON32UIMSC3IAWZZL57A277CMX2D4OOAC 2XZLORI35AOKD4YITN2XAVXDXZXRNUKNXJXPA2TTBAXYYLJB77GAC GYNLSVK3MDYAOAKNOUXTC27IRIDEOUVSOEEG5LZ2PS3T4DEL6DQAC KB6THMJJPQ56OLYYODIM5IVEF3IAPCAEC2HGH3C7LAEF24IW6XQQC STVQHBZPF2AV3H5PVVSZZSP47R6OA3IDTN66VSGE3Z5DWS3U43IAC XSZOCE4S65Y6NK5JBKQPDW4HEP5EAXYJPPFKJ6OJU32KNEAXGNHQC WUKQQ2HKS3KGG4LBEMGX7SLQISJ3PSFCEKQNWNGJICQSALMSKD7AC ZDN7BJ3JA3VL4AYWX3SV24GHP6NCAETJVAKAXKMIZTLHTWLUNMOQC DI5NRQZB4J4AARWOX7L4NXCPNLPOTXFZTMTQZRVY2HNK62GVL5ZQC CMUTTQVULRL5WISGIGHMKGLCKUG3YJRJCBIBNU7SMEJQXFQBAHWAC XPE6XANXV2TTPCF7BO5RNYGAZVHA3OKDFETBOWVGG7TVRCLRKAEQC FJF2WKUK6PNGAEJM5OGC2YHZVJLURWJ7TKVTOKC3XWSBO54QNIBAC SEI4JZIPV4FTRNGOAMKREFHPTMLLLQCG6J7DQ3L7CM3GSZOC7IFAC FD4FBI3AW3LE74XTQL5WTZ52KYXIYATW23YCPXV5QSJAUWTAY2XAC ZKAEZKAMMQWPQIV6X2CFQUUOG7RBJOE3MNXLBH4J3ZASUYTCZJAQC CITEDKPB6MKVZUEYEDE5ZKTNVY35HCOAXKDPYG7YLLEOVFNMSRXQC UC2L4AE6COAZGVMLTIV4INSNKRT2RGCEE6IRLOBKCBJZ3IV7GCRAC ZWBKKVT5TX2CSMBVEYZMQ6DLCXVHSD7SWFEKXWK6XKD6RP24MJJAC 6ZEY2NWHKGME25ZSTH6OYNG75JIOJECLVGY3KF4FIWSQBAVFRDAQC GZZOJ7ZUSBPI3HXIV5UCFNMCDAMZPPLISY2UDV73FDN74HZ3AWJAC X4XC4Q2MJC6Q45SOWNGIG2PWZFE4AG5E3M5ZW3OGV6ABUVC2XNGQC EXRAFG37562NH775A4LDPP5FNKXLPLIZSJ3FCOBINUDKRFBJHCXAC KOSCTMZC6VWQ5WST25FPATUAFCYG3JZGG3LF6MXSS42GPGHLDREQC KVTZ5BUW7V7RZ3STMQXF6LXVLMGRXDBEOPRBTHX2O4HELTQ2467QC 3ZZ75E2AOF7DO3TMR422QV7ZXNYOQZTOGF67LVSCEMX6N75Y36LAC W655S25G7CGI4XOZ2PKITKTH26VJ4QMZFRV2RPYNI4KIUJOIGVMAC HHQUHNVMK5HPDJJ53MBD4IE2TDC3BMQOARPHRQAOO43AWG2LNMOAC UPPVYBGC7MQBUCAAB6KW3R5KWHGASFTTXVUHEWRNP27SK3CI7UHQC TOXJRHV7ZUPHWXCA4TAG3YRBTIPUZQ5BNX34D3VD2JAIYLRN6XSAC RFSCYZWH7VQUGHAM374YUDGZGM5S4KT6NXWDMHXL4767SCRSL2DQC A2YH3UCN3AEAXWW7IHTJBBQY4XRBSV2TBOX3N47ZZGKE6L7P7L5AC A7XDW47SJ3ZYWRH64PLNI77XZTVX5FY6NX2LMT33L6BMUH3DYBMQC NPOFDGQF4CE72IZBT5Y7KPIBHWPPNOEPBYD5RTUHSVUJ2W4XFRVQC BA4YE6QGRTYONATHUP347OFUBUCWXQPNZ6Q5DIQ2DLJLRZJ6AC4AC V2LGTLIQHXMNYYKNNHAOYFLM6S3IU3CSGJLDJBIKMF5UU32DZWVAC DI4CW2M46SOKHZXATOP6HRLZB3A33FCWRFDQBIJHJY2BEDB537NQC 77T3TBBG5VN2Q4AUXHQVZTIFOSXDGTHW72J4MLX4P7LMYQURYZJAC 3LI5FAF5ULXOWBMTG4XCUOMUPVROSFDY6FWGE574OH4JGPMOPNVAC T64LKJ2RTUDFYSJQI7KF4WHZYXZHNEGNOS7ZMMCRIQZ4YN5LOOMAC CZP5PD5NYLDULLW43VOL6V75CH6DDEJO7H6JSGQSIV2WNSQF4A6QC 3XYTXGZS3CZ6H2DK6AQOLXN3BJM7N4RWRPQFQO67JMRWRJG6FHWQC Z4YYQXEE4OQPF22I4LD7RVQIBKK67AHCYR6C35MANUCIC4P3EPYQC W5YRNIBZIMTQLOKIBWBF7CHCIOLKXVHV7Y2AIKMKG7GCQSAVZKBAC RIKD63GT7RFV3UAV4BYD57GFXKXALWUP6J7AAHB3M6JVAZ3WFTXAC VWTWVVRECX62JABUZYFCTCPWTXXT3DB4635RIAGCKIQMGJ7VXRGAC ZEYYSYM7QBZG4Q67AN3CHYZQWO2DVVHXRAK6NX44UQD6VO3JTK3AC LR3QQRO4ZFYYIY4JJ7LJIO4VUK3EWESPIAPLPPIP4W7N75PSVQHQC DFDCD3LPJCYCNINXBXGFAYD4CT2SBI4RBITE7OK5D5QPTIWWMQKAC KCOCFOS6KMCTVS6K3WE6KOQSWC3QNWN2E36ASHQPP3Z3H4BHR3NQC YNTEYSW7NVBWQLJU45XRK7AWQR5NWFOB4UUVVQ62ERZOO2QJJGAAC LT5DF4XJ7RZIHKUTFXAVVMGMGTEOQA3F2LWK4MGMZM6FPVZXUHBQC DCAJEW7O2H4N3I5EXTSBH7ALLV452CORUPJT3YQXY7QXQQIFDC4AC JDCRIWCKVBGA2FL7PEIXATYG4INEISAGC7DDY46WPVQTEUB6PBNQC MBJSV73XEUIBF7LU6MUYQJQLCRXYY7LXD7KZZFLLOCEDOKU2EAQAC 3YMIGCYC3YUOZP5OBNSTOIJOT6ZTEDDKNMR5YCAJRD5JNBYFETYAC UBKNLKSJOZ6RR3BVEBTW2ID4NQ6DP34Z7HC6QA3755Q6YSTYSGEAC ZHN3HE2M5YXFA24J733T6IHQO55CXAQWQD7XIVM37AH23TWLVSQAC V65SHVVGO6ICRY4UZGNWCBK4DOWQWKARTJYOAWMMUW3WSRVMNKWQC ZVYDUU7PMUEFB45PVGMWBXBU3IOOEWB3GMCJ5G5QSK5DKRYZBHUQC K57REEWVDYAN7MA7OWR5CEROK536EK5SW5SVN3MT2J653P36NYZAC VSLQNAQBAGOJC2IV55V3W755UIPN47J4RTCCLCABRFFFUU5LT2JQC HO72KYBN3DYN6EC2RQUW4YP3CFBSY4X3ULYLFA2HQ36S5QGTGKIQC 6XBYIKVZHCOUS5XT2T3RQPCFG7SB6V33RLSKZFXTQMPINY5BMTTQC AIP3SFGCT25VRARONGIYW6W2VK5WW3BBL6HFEWE3WVDGVH4JBXWAC TEYHPVS3CWEWID4TOEBXRAYAWG5Q5Y7DIVJRCXSZPOBG745PXBNAC WJ65BKIQTRTLNUGFCDLYFBCJKWFT4Y4FIPEOQOFKDQGAYMJKIMQAC K3KDTBCJ2D6AHLKDKSV7KTKXOXO72KZ5CXBVLCYSKDNRCJ3EGDMQC AOQSHDBY3FLBJBFEIJQDYHGQOBECTYRN3KPWJWQMCVWDTB6L2IRQC RF4MODRCRWKMUG26O222X3ZY3MLE6X7BYZDWEQRLVUITTWYAGNUAC KQXMNV3RMRPSJCQVW4I2HSCFJQ6ZDRLNMJOTQI4MODB6UYA3ONQQC 7JZIPWVKXY3QA5QMTP24WPR7KKMMVXIHAQ4EGHNGCE7H4CRKROCAC BXFHQQPRDN25MCKA4CWNQ6YJEHMMRYOVIXCKA36WE4I4B4ZIZE5AC WLYMZDSEPWVZKL7SEBWGTTXMM5MHIVTR4TPYVCEASATV5QNLPAMAC WJWASFHAXBNMWHEXMKR53FLXPVUFVT44F2WKSJSA57V2UOZVSOJQC 4SNDY6U7TDCVRCARTEQ7JLATJFDMUMEFV2GSLKMQJY7RFNPU5HDQC TJQE7LZGYT5FUB6LR2GGKIV3BHXAAOP2V2SMYNLUNCZNQ4JNF5PAC 62FAY63A6J5JJOX2RHKOWKFCJ6SHAPJT67CQ4ZJ7EXCPH6QVTW5QC QHM7TVRG4QX2IU2VW2G4GDGCE2PZ7HKRIHMF3BEBGND2BHZ5ANGQC 6KL7TFY4VYQ67TCMYG53KQV55EP6PHHN73BFVW6VSDI27CPHVY6QC LGEY35AOE2SLV2QVSY277GADTDDS2S74ZBJY5XQIRHJJC2NQ6OKAC TVNP3QMGLXAKM4ESJ46RO7JR5AOVQDEVHSQOAGBZMR4UPMYKDPNQC BWTGJOX32366LU752LXMM3IBPZH5J5N4F25QY4S64AEK725OKUYAC This crate is a fork of [`anyhow`] by @dtolnay with a support for customized`Reports`. For more details on customization checkout the docs on
This crate is a fork of [`anyhow`] with a support for customizederror reports. For more details on customization checkout the docs on
- [`jane-eyre`]: A a report handler crate that exists purely for the pun.Currently just re-exports `color-eyre`.
- [`jane-eyre`]: A report handler crate that exists purely for the pun.Currently just re-exports `color-eyre`.
Use Eyre if you don't care what error type your functions return, you justwant it to be easy. This is common in application code. Use [thiserror] if youare a library that wants to design your own dedicated error type(s) so that onfailures the caller gets exactly the information that you choose.
Use `eyre` if you don't think you'll do anything with an error other thanreport it. This is common in application code. Use `thiserror` if you thinkyou need an error type that can be handled via match or reported. This iscommon in library crates where you don't know how your users will handleyour errors.
There are two main incompatibilities that you might encounter when porting acodebase from `anyhow` to `eyre`:- type inference errors when using `eyre!`- `.context` not being implemented for `Option`#### Type Inference ErrorsThe type inference issue is caused by the generic parameter, which isn'tpresent in `anyhow::Error`. Specifically, the following works in anyhow:```rustuse anyhow::anyhow;// Workslet val = get_optional_val().ok_or_else(|| anyhow!("failed to get value")).unwrap_err();```Where as with `eyre!` this will fail due to being unable to infer the type forthe Handler 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, eithervia your return type or a type annotation.```rust,compile_failuse eyre::eyre;// Brokenlet val = get_optional_val().ok_or_else(|| eyre!("failed to get value")).unwrap();// Workslet val: Report = get_optional_val().ok_or_else(|| eyre!("failed to get value")).unwrap();```
use backtrace::Backtrace;use eyre::EyreHandler;use std::error::Error;use std::{fmt, iter};fn main() -> eyre::Result<()> {// Install our custom eyre report hook for constructing our custom Handlersinstall().unwrap();// construct a report with, hopefully, our custom handler!let mut report = eyre::eyre!("hello from custom error town!");// manually set the custom msg for this report after it has been constructedif let Some(handler) = report.handler_mut().downcast_mut::<Handler>() {handler.custom_msg = Some("you're the best users, you know that right???");}// print that shit!!Err(report)}// define a handler that captures backtraces unless told not tofn install() -> Result<(), impl Error> {let capture_backtrace = std::env::var("RUST_BACKWARDS_TRACE").map(|val| val != "0").unwrap_or(true);let hook = Hook { capture_backtrace };eyre::set_hook(Box::new(move |e| Box::new(hook.make_handler(e))))}struct Hook {capture_backtrace: bool,}impl Hook {fn make_handler(&self, _error: &(dyn Error + 'static)) -> Handler {let backtrace = if self.capture_backtrace {Some(Backtrace::new())} else {None};Handler {backtrace,custom_msg: None,}}}struct Handler {// custom configured backtrace capturebacktrace: Option<Backtrace>,// customizable message payload associated with reportscustom_msg: Option<&'static str>,}impl EyreHandler for Handler {fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {if f.alternate() {return fmt::Debug::fmt(error, f);}let errors = iter::successors(Some(error), |error| error.source());for (ind, error) in errors.enumerate() {write!(f, "\n{:>4}: {}", ind, error)?;}if let Some(backtrace) = self.backtrace.as_ref() {writeln!(f, "\n\nBacktrace:\n{:?}", backtrace)?;}if let Some(msg) = self.custom_msg.as_ref() {writeln!(f, "\n\n{}", msg)?;}Ok(())}}
pub trait StdError<H>whereH: EyreHandler,{fn ext_report<D>(self, msg: D) -> Report<H>
pub trait StdError {fn ext_report<D>(self, msg: D) -> Report
impl<H> StdError<H> for Report<H>whereH: EyreHandler,{fn ext_report<D>(self, msg: D) -> Report<H>
impl StdError for Report {fn ext_report<D>(self, msg: D) -> Report
impl<T, H> ContextCompat<T, H> for Option<T>whereH: EyreHandler,{fn wrap_err<D>(self, msg: D) -> Result<T, Report<H>>
impl<T> ContextCompat<T> for Option<T> {fn wrap_err<D>(self, msg: D) -> Result<T, Report>
object_drop: object_drop::<E, H>,object_ref: object_ref::<E, H>,#[cfg(feature = "std")]object_mut: object_mut::<E, H>,object_boxed: object_boxed::<E, H>,object_downcast: object_downcast::<E, H>,object_drop_rest: object_drop_front::<E, H>,
object_drop: object_drop::<E>,object_ref: object_ref::<E>,object_mut: object_mut::<E>,object_boxed: object_boxed::<E>,object_downcast: object_downcast::<E>,object_drop_rest: object_drop_front::<E>,
object_drop: object_drop::<MessageError<M>, H>,object_ref: object_ref::<MessageError<M>, H>,#[cfg(feature = "std")]object_mut: object_mut::<MessageError<M>, H>,object_boxed: object_boxed::<MessageError<M>, H>,object_downcast: object_downcast::<M, H>,object_drop_rest: object_drop_front::<M, H>,
object_drop: object_drop::<MessageError<M>>,object_ref: object_ref::<MessageError<M>>,object_mut: object_mut::<MessageError<M>>,object_boxed: object_boxed::<MessageError<M>>,object_downcast: object_downcast::<M>,object_drop_rest: object_drop_front::<M>,
object_drop: object_drop::<DisplayError<M>, H>,object_ref: object_ref::<DisplayError<M>, H>,#[cfg(feature = "std")]object_mut: object_mut::<DisplayError<M>, H>,object_boxed: object_boxed::<DisplayError<M>, H>,object_downcast: object_downcast::<M, H>,object_drop_rest: object_drop_front::<M, H>,
object_drop: object_drop::<DisplayError<M>>,object_ref: object_ref::<DisplayError<M>>,object_mut: object_mut::<DisplayError<M>>,object_boxed: object_boxed::<DisplayError<M>>,object_downcast: object_downcast::<M>,object_drop_rest: object_drop_front::<M>,
object_drop: object_drop::<ContextError<D, E>, H>,object_ref: object_ref::<ContextError<D, E>, H>,#[cfg(feature = "std")]object_mut: object_mut::<ContextError<D, E>, H>,object_boxed: object_boxed::<ContextError<D, E>, H>,object_downcast: context_downcast::<D, E, H>,object_drop_rest: context_drop_rest::<D, E, H>,
object_drop: object_drop::<ContextError<D, E>>,object_ref: object_ref::<ContextError<D, E>>,object_mut: object_mut::<ContextError<D, E>>,object_boxed: object_boxed::<ContextError<D, E>>,object_downcast: context_downcast::<D, E>,object_drop_rest: context_drop_rest::<D, E>,
object_drop: object_drop::<BoxedError, H>,object_ref: object_ref::<BoxedError, H>,#[cfg(feature = "std")]object_mut: object_mut::<BoxedError, H>,object_boxed: object_boxed::<BoxedError, H>,object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>, H>,object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>, H>,
object_drop: object_drop::<BoxedError>,object_ref: object_ref::<BoxedError>,object_mut: object_mut::<BoxedError>,object_boxed: object_boxed::<BoxedError>,object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>,object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>,
object_drop: object_drop::<ContextError<D, Report<H>>, H>,object_ref: object_ref::<ContextError<D, Report<H>>, H>,#[cfg(feature = "std")]object_mut: object_mut::<ContextError<D, Report<H>>, H>,object_boxed: object_boxed::<ContextError<D, Report<H>>, H>,object_downcast: context_chain_downcast::<D, H>,object_drop_rest: context_chain_drop_rest::<D, H>,
object_drop: object_drop::<ContextError<D, Report>>,object_ref: object_ref::<ContextError<D, Report>>,object_mut: object_mut::<ContextError<D, Report>>,object_boxed: object_boxed::<ContextError<D, Report>>,object_downcast: context_chain_downcast::<D>,object_drop_rest: context_chain_drop_rest::<D>,
struct ErrorVTable<H>whereH: EyreHandler,{object_drop: unsafe fn(Box<ErrorImpl<(), H>>),object_ref: unsafe fn(&ErrorImpl<(), H>) -> &(dyn StdError + Send + Sync + 'static),#[cfg(feature = "std")]object_mut: unsafe fn(&mut ErrorImpl<(), H>) -> &mut (dyn StdError + Send + Sync + 'static),
struct ErrorVTable {object_drop: unsafe fn(Box<ErrorImpl<()>>),object_ref: unsafe fn(&ErrorImpl<()>) -> &(dyn StdError + Send + Sync + 'static),object_mut: unsafe fn(&mut ErrorImpl<()>) -> &mut (dyn StdError + Send + Sync + 'static),
object_boxed: unsafe fn(Box<ErrorImpl<(), H>>) -> Box<dyn StdError + Send + Sync + 'static>,object_downcast: unsafe fn(&ErrorImpl<(), H>, TypeId) -> Option<NonNull<()>>,object_drop_rest: unsafe fn(Box<ErrorImpl<(), H>>, TypeId),
object_boxed: unsafe fn(Box<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>,object_downcast: unsafe fn(&ErrorImpl<()>, TypeId) -> Option<NonNull<()>>,object_drop_rest: unsafe fn(Box<ErrorImpl<()>>, TypeId),
unsafe fn object_drop<E, H>(e: Box<ErrorImpl<(), H>>)whereH: EyreHandler,{
unsafe fn object_drop<E>(e: Box<ErrorImpl<()>>) {
unsafe fn object_drop_front<E, H>(e: Box<ErrorImpl<(), H>>, target: TypeId)whereH: EyreHandler,{
unsafe fn object_drop_front<E>(e: Box<ErrorImpl<()>>, target: TypeId) {
#[cfg(feature = "std")]unsafe fn context_downcast<D, E, H>(e: &ErrorImpl<(), H>, target: TypeId) -> Option<NonNull<()>>
unsafe fn context_downcast<D, E>(e: &ErrorImpl<()>, target: TypeId) -> Option<NonNull<()>>
pub(crate) struct ErrorImpl<E, H>whereH: EyreHandler,{vtable: &'static ErrorVTable<H>,pub(crate) handler: Option<H>,
pub(crate) struct ErrorImpl<E> {vtable: &'static ErrorVTable,pub(crate) handler: Option<Box<dyn EyreHandler>>,
impl<E, H> ErrorImpl<E, H>whereH: EyreHandler,{fn erase(&self) -> &ErrorImpl<(), H> {
impl<E> ErrorImpl<E> {fn erase(&self) -> &ErrorImpl<()> {
}}#[cfg(test)]mod test {use super::*;use crate::eyre;use std::num::ParseIntError;struct NonDefaultHandler;impl EyreHandler for NonDefaultHandler {#[allow(unused_variables)]fn default(error: &(dyn StdError + 'static)) -> Self {Self}fn debug(&self,_error: &(dyn StdError + 'static),_f: &mut core::fmt::Formatter<'_>,) -> core::fmt::Result {Ok(())}
fn _parse(s: &str) -> Result<i32, ParseIntError> {s.parse::<i32>()}fn _throw_error() -> Result<(), Report<NonDefaultHandler>> {match _parse("abc") {Ok(_) => Ok(()),Err(e) => Err(eyre!(e).wrap_err("try parsing an actual number")),}}
//! This crate is a fork of [`anyhow`] by @dtolnay with a support for customized//! `Reports`. For more details on customization checkout the docs on
//! This crate is a fork of [`anyhow`] with a support for customized//! error reports. For more details on customization checkout the docs on
//! - [`jane-eyre`]: A a report handler crate that exists purely for the pun.//! Currently just re-exports `color-eyre`.
//! - [`jane-eyre`]: A report handler crate that exists purely for the pun.//! Currently just re-exports `color-eyre`.
//! Use Eyre if you don't care what error type your functions return, you just//! want it to be easy. This is common in application code. Use [thiserror] if you//! are a library that wants to design your own dedicated error type(s) so that on//! failures the caller gets exactly the information that you choose.
//! Use `eyre` if you don't think you'll do anything with an error other than//! report it. This is common in application code. Use `thiserror` if you think//! you need an error type that can be handled via match or reported. This is//! common in library crates where you don't know how your users will handle//! your errors.
//! There are two main incompatibilities that you might encounter when porting a//! codebase from `anyhow` to `eyre`://!//! - type inference errors when using `eyre!`//! - `.context` not being implemented for `Option`//!//! #### Type Inference Errors//!//! The type inference issue is caused by the generic parameter, which isn't//! present in `anyhow::Error`. Specifically, the following works in anyhow://!//! ```rust//! # fn get_optional_val() -> Option<()> { None };//! use anyhow::anyhow;//!//! // Works//! let val = get_optional_val().ok_or_else(|| anyhow!("failed to get value")).unwrap_err();//! ```//!//! Where as with `eyre!` this will fail due to being unable to infer the type for//! the Handler 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,compile_fail//! use eyre::eyre;//!//! # fn get_optional_val() -> Option<()> { None };//! // Broken//! let val = get_optional_val().ok_or_else(|| eyre!("failed to get value")).unwrap();//!//! // Works//! let val: Report = get_optional_val().ok_or_else(|| eyre!("failed to get value")).unwrap();//! ```//!
mod alloc {#[cfg(not(feature = "std"))]extern crate alloc;#[cfg(not(feature = "std"))]pub(crate) use alloc::boxed::Box;#[cfg(feature = "std")]pub(crate) use std::boxed::Box;#[cfg(not(feature = "std"))]pub(crate) use alloc::string::String;// #[cfg(feature = "std")]// pub(crate) use std::string::String;}
/// to render the error and its cause chain yourself, it can be done something/// like this:////// ```/// use eyre::{WrapErr, Result};////// fn main() {/// if let Err(err) = try_main() {/// eprintln!("ERROR: {}", err);/// err.chain().skip(1).for_each(|cause| eprintln!("because: {}", cause));/// std::process::exit(1);/// }/// }
/// to render the error and its cause chain yourself, it can be done by defining/// your own [`EyreHandler`] and [`hook`] to use it.
/// fn try_main() -> Result<()> {/// # const IGNORE: &str = stringify! {/// .../// # };/// # Ok(())/// }/// ```pub struct Report<H = DefaultHandler>whereH: EyreHandler,{inner: ManuallyDrop<Box<ErrorImpl<(), H>>>,
/// [`EyreHandler`]: trait.EyreHandler.html/// [`hook`]: fn.set_hook.htmlpub struct Report {inner: ManuallyDrop<Box<ErrorImpl<()>>>,}type ErrorHook =Box<dyn Fn(&(dyn StdError + 'static)) -> Box<dyn EyreHandler> + Sync + Send + 'static>;static HOOK: OnceCell<ErrorHook> = OnceCell::new();/// Error indicating that `set_hook` was unable to install the provided ErrorHook#[derive(Debug)]pub struct InstallError;impl core::fmt::Display for InstallError {fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {f.write_str("cannot install provided ErrorHook, a hook has already been installed")}
/// In order to insert your own custom context and report format you must first/// implement the `eyre::EyreHandler` trait.
/// To customize the format and content of error reports from `eyre` you must/// first define a new `EyreHandler` type to capture and store the extra context/// and to define the format of how to display the chain of errors and this/// stored context. Once this type has been defined you must also define a global/// hook used to construct these handlers whenever `Report`s are constructed.
/// # use eyre::Chain;/// # use std::error::Error;/// use indenter::indented;
/// use std::error::Error;/// use std::{fmt, iter};////// fn main() -> eyre::Result<()> {/// // Install our custom eyre report hook for constructing our custom Handlers/// install().unwrap();////// // construct a report with, hopefully, our custom handler!/// let mut report = eyre::eyre!("hello from custom error town!");////// // manually set the custom msg for this report after it has been constructed/// if let Some(handler) = report.handler_mut().downcast_mut::<Handler>() {/// handler.custom_msg = Some("you're the best users, you know that right???");/// }////// // print that shit!!/// Err(report)/// }////// // define a handler that captures backtraces unless told not to/// fn install() -> Result<(), impl Error> {/// let capture_backtrace = std::env::var("RUST_BACKWARDS_TRACE")/// .map(|val| val != "0")/// .unwrap_or(true);////// let hook = Hook { capture_backtrace };////// eyre::set_hook(Box::new(move |e| Box::new(hook.make_handler(e))))/// }////// struct Hook {/// capture_backtrace: bool,/// }
/// pub struct Handler {/// backtrace: Backtrace,
/// impl Hook {/// fn make_handler(&self, _error: &(dyn Error + 'static)) -> Handler {/// let backtrace = if self.capture_backtrace {/// Some(Backtrace::new())/// } else {/// None/// };////// Handler {/// backtrace,/// custom_msg: None,/// }/// }/// }////// struct Handler {/// // custom configured backtrace capture/// backtrace: Option<Backtrace>,/// // customizable message payload associated with reports/// custom_msg: Option<&'static str>,
/// // .../// # #[allow(unused_variables)]/// # fn default(error: &(dyn Error + 'static)) -> Self {/// # let backtrace = Backtrace::new();/// # Self { backtrace }/// # }/// # fn debug(/// # &self,/// # error: &(dyn Error + 'static),/// # f: &mut core::fmt::Formatter<'_>,/// # ) -> core::fmt::Result {/// # use core::fmt::Write as _;/// # if f.alternate() {/// # return core::fmt::Debug::fmt(error, f);/// # }/// # write!(f, "{}", error)?;/// # if let Some(cause) = error.source() {/// # write!(f, "\n\nCaused by:")?;/// # let multiple = cause.source().is_some();/// # for (n, error) in Chain::new(cause).enumerate() {/// # writeln!(f)?;/// # if multiple {/// # write!(indented(f).ind(n), "{}", error)?;/// # } else {/// # write!(indented(f), "{}", error)?;/// # }/// # }/// # }/// # let backtrace = &self.backtrace;/// # write!(f, "\n\nStack backtrace:\n{:?}", backtrace)?;/// # Ok(())/// # }
/// fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {/// if f.alternate() {/// return fmt::Debug::fmt(error, f);/// }////// let errors = iter::successors(Some(error), |error| error.source());////// for (ind, error) in errors.enumerate() {/// write!(f, "\n{:>4}: {}", ind, error)?;/// }////// if let Some(backtrace) = self.backtrace.as_ref() {/// writeln!(f, "\n\nBacktrace:\n{:?}", backtrace)?;/// }////// if let Some(msg) = self.custom_msg.as_ref() {/// writeln!(f, "\n\n{}", msg)?;/// }////// Ok(())/// }
pub trait EyreHandler: Sized + Send + Sync + 'static {/// Default construct a `Handler` when constructing a `Report`.
pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {HOOK.set(hook).map_err(|_| InstallError)}fn capture_handler(error: &(dyn StdError + 'static)) -> Box<dyn EyreHandler> {let hook = HOOK.get_or_init(|| Box::new(DefaultHandler::default_with)).as_ref();hook(error)}impl dyn EyreHandler {
/// This method provides a reference to the error being wrapped to support conditional/// capturing of context like `backtrace` depending on whether the source error already/// captured one.
pub fn is<T: EyreHandler>(&self) -> bool {// Get `TypeId` of the type this function is instantiated with.let t = core::any::TypeId::of::<T>();// Get `TypeId` of the type in the trait object (`self`).let concrete = self.type_id();// Compare both `TypeId`s on equality.t == concrete}
/// ```rust/// use backtrace::Backtrace;/// use eyre::EyreHandler;/// # use eyre::Chain;/// use std::error::Error;////// pub struct Handler {/// backtrace: Backtrace,/// }////// impl EyreHandler for Handler {/// # #[allow(unused_variables)]/// fn default(error: &(dyn Error + 'static)) -> Self {/// let backtrace = Backtrace::new();////// Self { backtrace }/// }////// // .../// # fn debug(/// # &self,/// # error: &(dyn Error + 'static),/// # f: &mut core::fmt::Formatter<'_>,/// # ) -> core::fmt::Result {/// # use core::fmt::Write as _;/// # if f.alternate() {/// # return core::fmt::Debug::fmt(error, f);/// # }/// # write!(f, "{}", error)?;/// # if let Some(cause) = error.source() {/// # write!(f, "\n\nCaused by:")?;/// # let multiple = cause.source().is_some();/// # for (n, error) in Chain::new(cause).enumerate() {/// # writeln!(f)?;/// # if multiple {/// # write!(indenter::indented(f).ind(n), "{}", error)?;/// # } else {/// # write!(indenter::indented(f), "{}", error)?;/// # }/// # }/// # }/// # let backtrace = &self.backtrace;/// # write!(f, "\n\nStack backtrace:\n{:?}", backtrace)?;/// # Ok(())/// # }/// }/// ```fn default(err: &(dyn StdError + 'static)) -> Self;
pub fn downcast_mut<T: EyreHandler>(&mut self) -> Option<&mut T> {if self.is::<T>() {unsafe { Some(&mut *(self as *mut dyn EyreHandler as *mut T)) }} else {None}}}
#[allow(unused_variables)]fn default(error: &(dyn StdError + 'static)) -> Self {let backtrace = backtrace_if_absent!(error);Self { backtrace }}
pub trait WrapErr<T, E, H>: context::private::Sealed<H>whereH: EyreHandler,{
pub trait WrapErr<T, E>: context::private::Sealed {
pub trait ContextCompat<T, H>: context::private::Sealed<H>whereH: EyreHandler,{
pub trait ContextCompat<T>: context::private::Sealed {
| doesn't satisfy `Error: eyre::kind::TraitKind<_>`| doesn't satisfy `Error: std::convert::Into<eyre::Report<_>>`
| doesn't satisfy `Error: eyre::kind::TraitKind`| doesn't satisfy `Error: std::convert::Into<eyre::Report>`