GYNLSVK3MDYAOAKNOUXTC27IRIDEOUVSOEEG5LZ2PS3T4DEL6DQAC
EAYYVNCW3BKUSKSHWCHBYLDTSFC2CK6MTJ7DVA3O3KK3VC2IM2NAC
XSZOCE4S65Y6NK5JBKQPDW4HEP5EAXYJPPFKJ6OJU32KNEAXGNHQC
FH4KYVAA3AIVOQZTEXBT44UYTOAP6PJJFBSF6XQ5ALNGQO7OLKOAC
DI5NRQZB4J4AARWOX7L4NXCPNLPOTXFZTMTQZRVY2HNK62GVL5ZQC
77T3TBBG5VN2Q4AUXHQVZTIFOSXDGTHW72J4MLX4P7LMYQURYZJAC
EKYR4HDT6DHI7H5YMSHEBHXLPDCA2X2XNXYHDKHWGMPHNVTUBCMQC
YTH3GCSKUG34XBAAVP65UA67C26K2JDDL2N6PGYLKL2GG3MGFU6AC
YWW5TKMSPEGRZ52FQZ3SC4C3DEZ57U5XUO4LHZC34BJA7QR5NSCQC
6ASXQDFE2S6ADA43ELZTBDTRJ7BG3NFJIKVSAKEU5FMYNRWCHOPAC
OQCFKTKCBTWGXL27ZLWQSL4L5VPREJAYN7MVCCR4GXW6WLWYOUHAC
KB6THMJJPQ56OLYYODIM5IVEF3IAPCAEC2HGH3C7LAEF24IW6XQQC
X4XC4Q2MJC6Q45SOWNGIG2PWZFE4AG5E3M5ZW3OGV6ABUVC2XNGQC
XPE6XANXV2TTPCF7BO5RNYGAZVHA3OKDFETBOWVGG7TVRCLRKAEQC
ZKAEZKAMMQWPQIV6X2CFQUUOG7RBJOE3MNXLBH4J3ZASUYTCZJAQC
CITEDKPB6MKVZUEYEDE5ZKTNVY35HCOAXKDPYG7YLLEOVFNMSRXQC
UC2L4AE6COAZGVMLTIV4INSNKRT2RGCEE6IRLOBKCBJZ3IV7GCRAC
EXRAFG37562NH775A4LDPP5FNKXLPLIZSJ3FCOBINUDKRFBJHCXAC
XA5ZC3I5O3VTK5LP3IYKWMC6C4F5WPLBPMC7N2JUYRMEKGBYONJAC
3ZZ75E2AOF7DO3TMR422QV7ZXNYOQZTOGF67LVSCEMX6N75Y36LAC
NTM4ANW4APYTBQYTWJYYVETU2AFLRHUTHURDK5LYR3PHXGY3HMJQC
6ZEY2NWHKGME25ZSTH6OYNG75JIOJECLVGY3KF4FIWSQBAVFRDAQC
B35ATKRQB7JRNWXZD2YRYT6H73ZTQBUEXHZWZCHQEIOMSST5QJ6QC
V2LGTLIQHXMNYYKNNHAOYFLM6S3IU3CSGJLDJBIKMF5UU32DZWVAC
BQU6MTEH6QEW5E2HX3F2AAZ54AHIVDVOEE7FTCQTPLO23U5ILFIQC
CMUTTQVULRL5WISGIGHMKGLCKUG3YJRJCBIBNU7SMEJQXFQBAHWAC
HHQUHNVMK5HPDJJ53MBD4IE2TDC3BMQOARPHRQAOO43AWG2LNMOAC
RIKD63GT7RFV3UAV4BYD57GFXKXALWUP6J7AAHB3M6JVAZ3WFTXAC
F5QLL7RNKWB6DNLUZ7VKGTTYDVCH37YGR26SHZBIVAR37JJMQTXQC
LNM226ITXRMWOSX6GOJ4HO72BWFRBDKQTEZMF4QUJUACUIOKIEJQC
UM7DFUYLW4HSMBUDZY3R6ZNJRSX2E75C4DYV3MJAU57EUCGE6JLAC
YNTEYSW7NVBWQLJU45XRK7AWQR5NWFOB4UUVVQ62ERZOO2QJJGAAC
DFDCD3LPJCYCNINXBXGFAYD4CT2SBI4RBITE7OK5D5QPTIWWMQKAC
4SNDY6U7TDCVRCARTEQ7JLATJFDMUMEFV2GSLKMQJY7RFNPU5HDQC
SG6KZY4MUKOBPA7BBFRGGZIP36HWQ3WXJACMLBCZ57RX2HCWHWRQC
MBJSV73XEUIBF7LU6MUYQJQLCRXYY7LXD7KZZFLLOCEDOKU2EAQAC
3YMIGCYC3YUOZP5OBNSTOIJOT6ZTEDDKNMR5YCAJRD5JNBYFETYAC
OXKWHQFHTDDOWX3QDMHDWHCT3HFKWQS7Z7DEL3ILJBA7GNITA4GAC
6BNRWGF55J5M3YBWYNTWJCRJQSEHY7YRKOUBV43W7I2HCTFDJHUQC
UBKNLKSJOZ6RR3BVEBTW2ID4NQ6DP34Z7HC6QA3755Q6YSTYSGEAC
ZDN7BJ3JA3VL4AYWX3SV24GHP6NCAETJVAKAXKMIZTLHTWLUNMOQC
KVTZ5BUW7V7RZ3STMQXF6LXVLMGRXDBEOPRBTHX2O4HELTQ2467QC
C4Z57UJSN5U4LZSPXMQ22QOG4C6JG4CIROPT42SI6KBQQ7T32WQQC
VSLQNAQBAGOJC2IV55V3W755UIPN47J4RTCCLCABRFFFUU5LT2JQC
AOQSHDBY3FLBJBFEIJQDYHGQOBECTYRN3KPWJWQMCVWDTB6L2IRQC
RF4MODRCRWKMUG26O222X3ZY3MLE6X7BYZDWEQRLVUITTWYAGNUAC
GOPJFSDQLXOY7EGBNR26HON32UIMSC3IAWZZL57A277CMX2D4OOAC
BXFHQQPRDN25MCKA4CWNQ6YJEHMMRYOVIXCKA36WE4I4B4ZIZE5AC
A2YH3UCN3AEAXWW7IHTJBBQY4XRBSV2TBOX3N47ZZGKE6L7P7L5AC
It is not 100% compatible because there are some cases where `eyre` encounters
type inference errors but it should mostly work as a drop in replacement.
Specifically, the following works in anyhow:
#### 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:
let val: Report = get_optional_val.ok_or_else(|| eyre!("failed to get value")).unwrap();
let val: Report = get_optional_val().ok_or_else(|| eyre!("failed to get value")).unwrap();
```
#### `Context` and `Option`
As part of renaming `Context` to `WrapErr` we also intentionally do not
implement `WrapErr` for `Option`. This decision was made because `wrap_err`
implies that you're creating a new error that saves the old error as its
`source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
being somewhat meaningless.
Instead `eyre` intends for users to use the combinator functions provided by
`std` for converting `Option`s to `Result`s. So where you would write this with
anyhow:
```rust
use anyhow::Context;
let opt: Option<()> = None;
let result = opt.context("new error message");
With `eyre` we want users to write:
```rust
use eyre::{eyre, Result};
let opt: Option<()> = None;
let result: Result<()> = opt.ok_or_else(|| eyre!("new error message"));
```
However, to help with porting we do provide a `ContextCompat` trait which
implements `context` for options which you can import to make existing
`.context` calls compile.
/// Construct an iterator over a chain of errors via the `source` method
///
/// # Example
///
/// ```rust
/// use std::error::Error;
/// use std::fmt::{self, Write};
/// use eyre::Chain;
/// use indenter::indented;
///
/// fn report(error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let mut errors = Chain::new(error).enumerate();
/// for (i, error) in errors {
/// writeln!(f)?;
/// write!(indented(f).ind(i), "{}", error)?;
/// }
///
/// Ok(())
/// }
/// ```
}
}
impl<T, C> ContextCompat<T, C> for Option<T>
where
C: EyreContext,
{
fn wrap_err<D>(self, msg: D) -> Result<T, Report<C>>
where
D: Display + Send + Sync + 'static,
{
self.context(msg)
}
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report<C>>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
self.with_context(msg)
}
fn context<D>(self, msg: D) -> Result<T, Report<C>>
where
D: Display + Send + Sync + 'static,
{
self.ok_or_else(|| Report::from_display(msg))
}
fn with_context<D, F>(self, msg: F) -> Result<T, Report<C>>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
self.ok_or_else(|| Report::from_display(msg()))
unsafe { Report::construct(error, vtable, context) }
}
pub(crate) fn from_display<M>(message: M) -> Self
where
M: Display + Send + Sync + 'static,
{
use crate::wrapper::{DisplayError, NoneError};
let error: DisplayError<M> = DisplayError(message);
let vtable = &ErrorVTable {
object_drop: object_drop::<DisplayError<M>, C>,
object_ref: object_ref::<DisplayError<M>, C>,
#[cfg(feature = "std")]
object_mut: object_mut::<DisplayError<M>, C>,
object_boxed: object_boxed::<DisplayError<M>, C>,
object_downcast: object_downcast::<M, C>,
object_drop_rest: object_drop_front::<M, C>,
};
// Safety: DisplayError is repr(transparent) so it is okay for the
// vtable to allow casting the DisplayError<M> to M.
let context = Some(C::default(&NoneError));
//! It is not 100% compatible because there are some cases where `eyre` encounters
//! type inference errors but it should mostly work as a drop in replacement.
//! Specifically, the following works in anyhow:
//! 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:
//! let val: Report = get_optional_val.ok_or_else(|| eyre!("failed to get value")).unwrap();
//! let val: Report = get_optional_val().ok_or_else(|| eyre!("failed to get value")).unwrap();
//! ```
//!
//! #### `Context` and `Option`
//!
//! As part of renaming `Context` to `WrapErr` we also intentionally do not
//! implement `WrapErr` for `Option`. This decision was made because `wrap_err`
//! implies that you're creating a new error that saves the old error as its
//! `source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
//! being somewhat meaningless.
//!
//! Instead `eyre` intends for users to use the combinator functions provided by
//! `std` for converting `Option`s to `Result`s. So where you would write this with
//! anyhow:
//!
//! ```rust
//! use anyhow::Context;
//!
//! let opt: Option<()> = None;
//! let result = opt.context("new error message");
//! ```
//!
//! With `eyre` we want users to write:
//!
//! ```rust
//! use eyre::{eyre, Result};
//!
//! let opt: Option<()> = None;
//! let result: Result<()> = opt.ok_or_else(|| eyre!("new error message"));
#![warn(
missing_debug_implementations,
missing_docs,
missing_doc_code_examples,
rust_2018_idioms,
unreachable_pub,
bad_style,
const_err,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
no_mangle_generic_items,
overflowing_literals,
path_statements,
patterns_in_fns_without_body,
private_in_public,
unconditional_recursion,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true
)]
/// ```
///
/// # Wrapping Types That Don't impl `Error` (e.g. `&str` and `Box<dyn Error>`)
///
/// Due to restrictions for coherence `Report` cannot impl `From` for types that don't impl
/// `Error`. Attempts to do so will give "this type might implement Error in the future" as an
/// error. As such, `wrap_err`, which uses `From` under the hood, cannot be used to wrap these
/// types. Instead we encourage you to use the combinators provided for `Result` in `std`/`core`.
///
/// For example, instead of this:
///
/// ```rust,compile_fail
/// use std::error::Error;
/// use eyre::{WrapErr, Report};
///
/// fn wrap_example(err: Result<(), Box<dyn Error + Send + Sync + 'static>>) -> Result<(), Report> {
/// err.wrap_err("saw a downstream error")
/// }
/// ```rust
/// use std::error::Error;
/// use eyre::{WrapErr, Report, eyre};
///
/// fn wrap_example(err: Result<(), Box<dyn Error + Send + Sync + 'static>>) -> Result<(), Report> {
/// err.map_err(|e| eyre!(e)).wrap_err("saw a downstream error")
/// }
/// ```
///
fn with_context<D, F>(self, f: F) -> Result<T, Report<C>>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D;
}
/// Provides the `context` method for `Option` when porting from `anyhow`
///
/// This trait is sealed and cannot be implemented for types outside of
/// `eyre`.
///
/// ## Why Doesn't `Eyre` impl `WrapErr` for `Option`?
///
/// `eyre` doesn't impl `WrapErr` for `Option` because `wrap_err` implies that you're creating a
/// new error that saves the previous error as its `source`. Calling `wrap_err` on an `Option` is
/// meaningless because there is no source error. `anyhow` avoids this issue by using a different
/// mental model where you're adding "context" to an error, though this not a mental model for
/// error handling that `eyre` agrees with.
///
/// Instead, `eyre` encourages users to think of each error as distinct, where the previous error
/// is the context being saved by the new error, which is backwards compared to anyhow's model. In
/// this model you're encouraged to use combinators provided by `std` for `Option` to convert an
/// option to a `Result`
///
/// # Example
///
/// Instead of:
///
/// ```rust
/// use eyre::ContextCompat;
///
/// fn get_thing(mut things: impl Iterator<Item = u32>) -> eyre::Result<u32> {
/// things
/// .find(|&thing| thing == 42)
/// .context("the thing wasnt in the list")
/// }
/// ```
///
/// We encourage you to use this:
///
/// ```rust
/// use eyre::eyre;
///
/// fn get_thing(mut things: impl Iterator<Item = u32>) -> eyre::Result<u32> {
/// things
/// .find(|&thing| thing == 42)
/// .ok_or_else(|| eyre!("the thing wasnt in the list"))
/// }
/// ```
pub trait ContextCompat<T, C>: context::private::Sealed<C>
where
C: EyreContext,
{
/// Compatibility version of `wrap_err` for creating new errors with new source on `Option`
/// when porting from `anyhow`
fn context<D>(self, msg: D) -> Result<T, Report<C>>
where
D: Display + Send + Sync + 'static;
/// Compatibility version of `wrap_err_with` for creating new errors with new source on `Option`
/// when porting from `anyhow`