eyre/
lib.rs

1//! This library provides [`eyre::Report`][Report], a trait object based
2//! error handling type for easy idiomatic error handling and reporting in Rust
3//! applications.
4//!
5//! This crate is a fork of [`anyhow`]  with support for customized
6//! error reports. For more details on customization, check out the docs on
7//! [`eyre::EyreHandler`].
8//!
9//! ## Custom Report Handlers
10//!
11//! The heart of this crate is its ability to swap out the Handler type to change
12//! what information is carried alongside errors and how the end report is
13//! formatted. This crate is meant to be used alongside companion crates that
14//! customize its behavior. Below is a list of known crates that export report
15//! handlers for eyre and short summaries of what features they provide.
16//!
17//! - [`stable-eyre`]: Switches the backtrace type from `std`'s to `backtrace-rs`'s
18//!   so that it can be captured on stable. The report format is identical to
19//!   `DefaultHandler`'s report format.
20//! - [`color-eyre`]: Captures a `backtrace::Backtrace` and a
21//!   `tracing_error::SpanTrace`. Provides a `Section` trait for attaching warnings
22//!   and suggestions to error reports. The end report is then pretty printed with
23//!   the help of [`color-backtrace`], [`color-spantrace`], and `ansi_term`. Check
24//!   out the README on [`color-eyre`] for details on the report format.
25//! - [`simple-eyre`]: A minimal `EyreHandler` that captures no additional
26//!   information, for when you do not wish to capture `Backtrace`s with errors.
27//! - [`jane-eyre`]: A report handler crate that exists purely for the pun.
28//!   Currently just re-exports `color-eyre`.
29//!
30//! ## Usage Recommendations and Stability Considerations
31//!
32//! **We recommend users do not re-export types from this library as part their
33//! own public API for libraries with external users.** The main reason for this
34//! is that it will make your library API break if we ever bump the major version
35//! number on eyre and your users upgrade the eyre version they use in their
36//! application code before you upgrade your own eyre dep version[^1].
37//!
38//! However, even beyond this API stability hazard, there are other good reasons
39//! to avoid using `eyre::Report` as your public error type.
40//!
41//! - You export an undocumented error interface that is otherwise still
42//! accessible via downcast, making it hard for users to react to specific
43//! errors while not preventing them from depending on details you didn't mean
44//! to make part of your public API.
45//!   - This in turn makes the error types of all libraries you use a part of
46//!   your public API as well, and makes changing any of those libraries into
47//!   undetectable runtime breakage.
48//! - If many of your errors are constructed from strings, you encourage your
49//! users to use string comparison for reacting to specific errors, which is
50//! brittle and turns updating error messages into potentially undetectable
51//! runtime breakage.
52//!
53//! ## Details
54//!
55//! - Use `Result<T, eyre::Report>`, or equivalently `eyre::Result<T>`, as the
56//!   return type of any fallible function.
57//!
58//!   Within the function, use `?` to easily propagate any error that implements the
59//!   `std::error::Error` trait.
60//!
61//!   ```rust
62//!   # pub trait Deserialize {}
63//!   #
64//!   # mod serde_json {
65//!   #     use super::Deserialize;
66//!   #     use std::io;
67//!   #
68//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
69//!   #         unimplemented!()
70//!   #     }
71//!   # }
72//!   #
73//!   # struct ClusterMap;
74//!   #
75//!   # impl Deserialize for ClusterMap {}
76//!   #
77//!   use eyre::Result;
78//!
79//!   fn get_cluster_info() -> Result<ClusterMap> {
80//!       let config = std::fs::read_to_string("cluster.json")?;
81//!       let map: ClusterMap = serde_json::from_str(&config)?;
82//!       Ok(map)
83//!   }
84//!   #
85//!   # fn main() {}
86//!   ```
87//!
88//! - Wrap a lower level error with a new error created from a message to help the
89//!   person troubleshooting understand the chain of failures that occurred. A
90//!   low-level error like "No such file or directory" can be annoying to debug
91//!   without more information about what higher level step the application was in
92//!   the middle of.
93//!
94//!   ```rust
95//!   # struct It;
96//!   #
97//!   # impl It {
98//!   #     fn detach(&self) -> Result<()> {
99//!   #         unimplemented!()
100//!   #     }
101//!   # }
102//!   #
103//!   use eyre::{WrapErr, Result};
104//!
105//!   fn main() -> Result<()> {
106//!       # return Ok(());
107//!       #
108//!       # const _: &str = stringify! {
109//!       ...
110//!       # };
111//!       #
112//!       # let it = It;
113//!       # let path = "./path/to/instrs.json";
114//!       #
115//!       it.detach().wrap_err("Failed to detach the important thing")?;
116//!
117//!       let content = std::fs::read(path)
118//!           .wrap_err_with(|| format!("Failed to read instrs from {}", path))?;
119//!       #
120//!       # const _: &str = stringify! {
121//!       ...
122//!       # };
123//!       #
124//!       # Ok(())
125//!   }
126//!   ```
127//!
128//!   ```console
129//!   Error: Failed to read instrs from ./path/to/instrs.json
130//!
131//!   Caused by:
132//!       No such file or directory (os error 2)
133//!   ```
134//!
135//! - Downcasting is supported and can be done by value, by shared reference, or by
136//!   mutable reference as needed.
137//!
138//!   ```rust
139//!   # use eyre::{Report, eyre};
140//!   # use std::fmt::{self, Display};
141//!   # use std::task::Poll;
142//!   #
143//!   # #[derive(Debug)]
144//!   # enum DataStoreError {
145//!   #     Censored(()),
146//!   # }
147//!   #
148//!   # impl Display for DataStoreError {
149//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
150//!   #         unimplemented!()
151//!   #     }
152//!   # }
153//!   #
154//!   # impl std::error::Error for DataStoreError {}
155//!   #
156//!   # const REDACTED_CONTENT: () = ();
157//!   #
158//!   # #[cfg(not(feature = "auto-install"))]
159//!   # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
160//!   #
161//!   # let error: Report = eyre!("...");
162//!   # let root_cause = &error;
163//!   #
164//!   # let ret =
165//!   // If the error was caused by redaction, then return a
166//!   // tombstone instead of the content.
167//!   match root_cause.downcast_ref::<DataStoreError>() {
168//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
169//!       None => Err(error),
170//!   }
171//!   # ;
172//!   ```
173//!
174//! - If using the nightly channel, a backtrace is captured and printed with the
175//!   error if the underlying error type does not already provide its own. In order
176//!   to see backtraces, they must be enabled through the environment variables
177//!   described in [`std::backtrace`]:
178//!
179//!   - If you want panics and errors to both have backtraces, set
180//!     `RUST_BACKTRACE=1`;
181//!   - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`;
182//!   - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and
183//!     `RUST_LIB_BACKTRACE=0`.
184//!
185//!   The tracking issue for this feature is [rust-lang/rust#53487].
186//!
187//!   [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables
188//!   [rust-lang/rust#53487]: https://github.com/rust-lang/rust/issues/53487
189//!
190//! - Eyre works with any error type that has an impl of `std::error::Error`,
191//!   including ones defined in your crate. We do not bundle a `derive(Error)` macro
192//!   but you can write the impls yourself or use a standalone macro like
193//!   [thiserror].
194//!
195//!   ```rust
196//!   use thiserror::Error;
197//!
198//!   #[derive(Error, Debug)]
199//!   pub enum FormatError {
200//!       #[error("Invalid header (expected {expected:?}, got {found:?})")]
201//!       InvalidHeader {
202//!           expected: String,
203//!           found: String,
204//!       },
205//!       #[error("Missing attribute: {0}")]
206//!       MissingAttribute(String),
207//!   }
208//!   ```
209//!
210//! - One-off error messages can be constructed using the `eyre!` macro, which
211//!   supports string interpolation and produces an `eyre::Report`.
212//!
213//!   ```rust
214//!   # use eyre::{eyre, Result};
215//!   #
216//!   # fn demo() -> Result<()> {
217//!   #     let missing = "...";
218//!   return Err(eyre!("Missing attribute: {}", missing));
219//!   #     Ok(())
220//!   # }
221//!   ```
222//!
223//! - On newer versions of the compiler (i.e. 1.58 and later) this macro also
224//!   supports format args captures.
225//!
226//!   ```rust
227//!   # use eyre::{eyre, Result};
228//!   #
229//!   # fn demo() -> Result<()> {
230//!   #     let missing = "...";
231//!   # #[cfg(not(eyre_no_fmt_args_capture))]
232//!   return Err(eyre!("Missing attribute: {missing}"));
233//!   #     Ok(())
234//!   # }
235//!   ```
236//!
237//! ## No-std support
238//!
239//! No-std support was removed in 2020 in [commit 608a16a] due to unaddressed upstream breakages.
240//!
241//! [commit 608a16a]: https://github.com/eyre-rs/eyre/pull/29/commits/608a16aa2c2c27eca6c88001cc94c6973c18f1d5
242//!
243//! ## Comparison to failure
244//!
245//! The `eyre::Report` type works something like `failure::Error`, but unlike
246//! failure ours is built around the standard library's `std::error::Error` trait
247//! rather than a separate trait `failure::Fail`. The standard library has adopted
248//! the necessary improvements for this to be possible as part of [RFC 2504].
249//!
250//! [RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
251//!
252//! ## Comparison to thiserror
253//!
254//! Use `eyre` if you don't think you'll do anything with an error other than
255//! report it. This is common in application code. Use `thiserror` if you think
256//! you need an error type that can be handled via match or reported. This is
257//! common in library crates where you don't know how your users will handle
258//! your errors.
259//!
260//! [thiserror]: https://github.com/dtolnay/thiserror
261//!
262//! ## Compatibility with `anyhow`
263//!
264//! This crate does its best to be usable as a drop in replacement of `anyhow` and
265//! vice-versa by re-exporting all of the renamed APIs with the names used in
266//! `anyhow`, though there are some differences still.
267//!
268//! #### `Context` and `Option`
269//!
270//! As part of renaming `Context` to `WrapErr` we also intentionally do not
271//! implement `WrapErr` for `Option`. This decision was made because `wrap_err`
272//! implies that you're creating a new error that saves the old error as its
273//! `source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
274//! being somewhat meaningless.
275//!
276//! Instead `eyre` offers [`OptionExt::ok_or_eyre`] to yield _static_ errors from `None`,
277//! and intends for users to use the combinator functions provided by
278//! `std`, converting `Option`s to `Result`s, for _dynamic_ errors.
279//! So where you would write this with
280//! anyhow:
281//!
282//! ```rust
283//! use anyhow::Context;
284//!
285//! let opt: Option<()> = None;
286//! let result_static = opt.context("static error message");
287//! let result_dynamic = opt.with_context(|| format!("{} error message", "dynamic"));
288//! ```
289//!
290//! With `eyre` we want users to write:
291//!
292//! ```rust
293//! use eyre::{eyre, OptionExt, Result};
294//!
295//! # #[cfg(not(feature = "auto-install"))]
296//! # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
297//! #
298//! let opt: Option<()> = None;
299//! let result_static: Result<()> = opt.ok_or_eyre("static error message");
300//! let result_dynamic: Result<()> = opt.ok_or_else(|| eyre!("{} error message", "dynamic"));
301//! ```
302//!
303//! **NOTE**: However, to help with porting we do provide a `ContextCompat` trait which
304//! implements `context` for options which you can import to make existing
305//! `.context` calls compile.
306//!
307//! [^1]: example and explanation of breakage <https://github.com/eyre-rs/eyre/issues/30#issuecomment-647650361>
308//!
309//! [Report]: https://docs.rs/eyre/*/eyre/struct.Report.html
310//! [`eyre::EyreHandler`]: https://docs.rs/eyre/*/eyre/trait.EyreHandler.html
311//! [`eyre::WrapErr`]: https://docs.rs/eyre/*/eyre/trait.WrapErr.html
312//! [`anyhow::Context`]: https://docs.rs/anyhow/*/anyhow/trait.Context.html
313//! [`anyhow`]: https://github.com/dtolnay/anyhow
314//! [`tracing_error::SpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/struct.SpanTrace.html
315//! [`stable-eyre`]: https://github.com/eyre-rs/stable-eyre
316//! [`color-eyre`]: https://github.com/eyre-rs/color-eyre
317//! [`jane-eyre`]: https://github.com/yaahc/jane-eyre
318//! [`simple-eyre`]: https://github.com/eyre-rs/simple-eyre
319//! [`color-spantrace`]: https://github.com/eyre-rs/color-spantrace
320//! [`color-backtrace`]: https://github.com/athre0z/color-backtrace
321#![doc(html_root_url = "https://docs.rs/eyre/0.6.12")]
322#![cfg_attr(
323    nightly,
324    feature(rustdoc_missing_doc_code_examples),
325    warn(rustdoc::missing_doc_code_examples)
326)]
327#![warn(
328    missing_debug_implementations,
329    missing_docs,
330    unsafe_op_in_unsafe_fn,
331    rust_2018_idioms,
332    unreachable_pub,
333    bad_style,
334    dead_code,
335    improper_ctypes,
336    non_shorthand_field_patterns,
337    no_mangle_generic_items,
338    overflowing_literals,
339    path_statements,
340    patterns_in_fns_without_body,
341    unconditional_recursion,
342    unused,
343    unused_allocation,
344    unused_comparisons,
345    unused_parens,
346    while_true
347)]
348#![cfg_attr(backtrace, feature(backtrace))]
349#![cfg_attr(doc_cfg, feature(doc_cfg))]
350#![allow(
351    clippy::needless_doctest_main,
352    clippy::new_ret_no_self,
353    clippy::wrong_self_convention
354)]
355
356extern crate alloc;
357
358#[macro_use]
359mod backtrace;
360mod chain;
361mod context;
362mod error;
363mod fmt;
364mod kind;
365mod macros;
366mod option;
367mod ptr;
368mod wrapper;
369
370use crate::backtrace::Backtrace;
371use crate::error::ErrorImpl;
372use core::fmt::{Debug, Display};
373
374use std::error::Error as StdError;
375
376pub use eyre as format_err;
377/// Compatibility re-export of `eyre` for interop with `anyhow`
378pub use eyre as anyhow;
379use once_cell::sync::OnceCell;
380use ptr::OwnedPtr;
381#[doc(hidden)]
382pub use DefaultHandler as DefaultContext;
383#[doc(hidden)]
384pub use EyreHandler as EyreContext;
385#[doc(hidden)]
386pub use Report as ErrReport;
387/// Compatibility re-export of `Report` for interop with `anyhow`
388pub use Report as Error;
389/// Compatibility re-export of `WrapErr` for interop with `anyhow`
390pub use WrapErr as Context;
391
392/// The core error reporting type of the library, a wrapper around a dynamic error reporting type.
393///
394/// `Report` works a lot like `Box<dyn std::error::Error>`, but with these
395/// differences:
396///
397/// - `Report` requires that the error is `Send`, `Sync`, and `'static`.
398/// - `Report` guarantees that a backtrace is available, even if the underlying
399///   error type does not provide one.
400/// - `Report` is represented as a narrow pointer &mdash; exactly one word in
401///   size instead of two.
402///
403/// # Display representations
404///
405/// When you print an error object using "{}" or to_string(), only the outermost underlying error
406/// is printed, not any of the lower level causes. This is exactly as if you had called the Display
407/// impl of the error from which you constructed your eyre::Report.
408///
409/// ```console
410/// Failed to read instrs from ./path/to/instrs.json
411/// ```
412///
413/// To print causes as well using eyre's default formatting of causes, use the
414/// alternate selector "{:#}".
415///
416/// ```console
417/// Failed to read instrs from ./path/to/instrs.json: No such file or directory (os error 2)
418/// ```
419///
420/// The Debug format "{:?}" includes your backtrace if one was captured. Note
421/// that this is the representation you get by default if you return an error
422/// from `fn main` instead of printing it explicitly yourself.
423///
424/// ```console
425/// Error: Failed to read instrs from ./path/to/instrs.json
426///
427/// Caused by:
428///     No such file or directory (os error 2)
429///
430/// Stack backtrace:
431///    0: <E as eyre::context::ext::StdError>::ext_report
432///              at /git/eyre/src/backtrace.rs:26
433///    1: core::result::Result<T,E>::map_err
434///              at /git/rustc/src/libcore/result.rs:596
435///    2: eyre::context::<impl eyre::WrapErr<T,E,H> for core::result::Result<T,E>>::wrap_err_with
436///              at /git/eyre/src/context.rs:58
437///    3: testing::main
438///              at src/main.rs:5
439///    4: std::rt::lang_start
440///              at /git/rustc/src/libstd/rt.rs:61
441///    5: main
442///    6: __libc_start_main
443///    7: _start
444/// ```
445///
446/// To see a conventional struct-style Debug representation, use "{:#?}".
447///
448/// ```console
449/// Error {
450///     msg: "Failed to read instrs from ./path/to/instrs.json",
451///     source: Os {
452///         code: 2,
453///         kind: NotFound,
454///         message: "No such file or directory",
455///     },
456/// }
457/// ```
458///
459/// If none of the built-in representations are appropriate and you would prefer
460/// to render the error and its cause chain yourself, it can be done by defining
461/// your own [`EyreHandler`] and [`hook`] to use it.
462///
463/// [`EyreHandler`]: trait.EyreHandler.html
464/// [`hook`]: fn.set_hook.html
465#[must_use]
466pub struct Report {
467    inner: OwnedPtr<ErrorImpl<()>>,
468}
469
470type ErrorHook =
471    Box<dyn Fn(&(dyn StdError + 'static)) -> Box<dyn EyreHandler> + Sync + Send + 'static>;
472
473static HOOK: OnceCell<ErrorHook> = OnceCell::new();
474
475/// Error indicating that `set_hook` was unable to install the provided ErrorHook
476#[derive(Debug, Clone, Copy)]
477pub struct InstallError;
478
479impl core::fmt::Display for InstallError {
480    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
481        f.write_str("cannot install provided ErrorHook, a hook has already been installed")
482    }
483}
484
485impl StdError for InstallError {}
486
487/// Install the provided error hook for constructing EyreHandlers when converting
488/// Errors to Reports
489///
490/// # Details
491///
492/// To customize the format and content of error reports from `eyre` you must
493/// first define a new `EyreHandler` type to capture and store the extra context
494/// and to define the format of how to display the chain of errors and this
495/// stored context. Once this type has been defined you must also define a global
496/// hook used to construct these handlers whenever `Report`s are constructed.
497///
498/// # Examples
499///
500/// ```rust,should_panic
501/// use backtrace::Backtrace;
502/// use eyre::EyreHandler;
503/// use std::error::Error;
504/// use std::{fmt, iter};
505///
506/// fn main() -> eyre::Result<()> {
507///     // Install our custom eyre report hook for constructing our custom Handlers
508///     install().unwrap();
509///
510///     // construct a report with, hopefully, our custom handler!
511///     let mut report = eyre::eyre!("hello from custom error town!");
512///
513///     // manually set the custom msg for this report after it has been constructed
514///     if let Some(handler) = report.handler_mut().downcast_mut::<Handler>() {
515///         handler.custom_msg = Some("you're the best users, you know that right???");
516///     }
517///
518///     // print that shit!!
519///     Err(report)
520/// }
521///
522/// // define a handler that captures backtraces unless told not to
523/// fn install() -> Result<(), impl Error> {
524///     let capture_backtrace = std::env::var("RUST_BACKWARDS_TRACE")
525///         .map(|val| val != "0")
526///         .unwrap_or(true);
527///
528///     let hook = Hook { capture_backtrace };
529///
530///     eyre::set_hook(Box::new(move |e| Box::new(hook.make_handler(e))))
531/// }
532///
533/// struct Hook {
534///     capture_backtrace: bool,
535/// }
536///
537/// impl Hook {
538///     fn make_handler(&self, _error: &(dyn Error + 'static)) -> Handler {
539///         let backtrace = if self.capture_backtrace {
540///             Some(Backtrace::new())
541///         } else {
542///             None
543///         };
544///
545///         Handler {
546///             backtrace,
547///             custom_msg: None,
548///         }
549///     }
550/// }
551///
552/// struct Handler {
553///     // custom configured backtrace capture
554///     backtrace: Option<Backtrace>,
555///     // customizable message payload associated with reports
556///     custom_msg: Option<&'static str>,
557/// }
558///
559/// impl EyreHandler for Handler {
560///     fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
561///         if f.alternate() {
562///             return fmt::Debug::fmt(error, f);
563///         }
564///
565///         let errors = iter::successors(Some(error), |error| (*error).source());
566///
567///         for (ind, error) in errors.enumerate() {
568///             write!(f, "\n{:>4}: {}", ind, error)?;
569///         }
570///
571///         if let Some(backtrace) = self.backtrace.as_ref() {
572///             writeln!(f, "\n\nBacktrace:\n{:?}", backtrace)?;
573///         }
574///
575///         if let Some(msg) = self.custom_msg.as_ref() {
576///             writeln!(f, "\n\n{}", msg)?;
577///         }
578///
579///         Ok(())
580///     }
581/// }
582/// ```
583pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
584    HOOK.set(hook).map_err(|_| InstallError)
585}
586
587#[cfg_attr(track_caller, track_caller)]
588#[cfg_attr(not(track_caller), allow(unused_mut))]
589fn capture_handler(error: &(dyn StdError + 'static)) -> Box<dyn EyreHandler> {
590    #[cfg(not(feature = "auto-install"))]
591    let hook = HOOK
592        .get()
593        .expect("a handler must always be installed if the `auto-install` feature is disabled")
594        .as_ref();
595
596    #[cfg(feature = "auto-install")]
597    let hook = HOOK
598        .get_or_init(|| Box::new(DefaultHandler::default_with))
599        .as_ref();
600
601    let mut handler = hook(error);
602
603    #[cfg(track_caller)]
604    {
605        handler.track_caller(std::panic::Location::caller())
606    }
607
608    handler
609}
610
611impl dyn EyreHandler {
612    ///
613    pub fn is<T: EyreHandler>(&self) -> bool {
614        // Get `TypeId` of the type this function is instantiated with.
615        let t = core::any::TypeId::of::<T>();
616
617        // Get `TypeId` of the type in the trait object (`self`).
618        let concrete = self.type_id();
619
620        // Compare both `TypeId`s on equality.
621        t == concrete
622    }
623
624    ///
625    pub fn downcast_ref<T: EyreHandler>(&self) -> Option<&T> {
626        if self.is::<T>() {
627            unsafe { Some(&*(self as *const dyn EyreHandler as *const T)) }
628        } else {
629            None
630        }
631    }
632
633    ///
634    pub fn downcast_mut<T: EyreHandler>(&mut self) -> Option<&mut T> {
635        if self.is::<T>() {
636            unsafe { Some(&mut *(self as *mut dyn EyreHandler as *mut T)) }
637        } else {
638            None
639        }
640    }
641}
642
643/// Error Report Handler trait for customizing `eyre::Report`
644pub trait EyreHandler: core::any::Any + Send + Sync {
645    /// Define the report format
646    ///
647    /// Used to override the report format of `eyre::Report`
648    ///
649    /// # Example
650    ///
651    /// ```rust
652    /// use backtrace::Backtrace;
653    /// use eyre::EyreHandler;
654    /// use eyre::Chain;
655    /// use std::error::Error;
656    /// use indenter::indented;
657    ///
658    /// pub struct Handler {
659    ///     backtrace: Backtrace,
660    /// }
661    ///
662    /// impl EyreHandler for Handler {
663    ///     fn debug(
664    ///         &self,
665    ///         error: &(dyn Error + 'static),
666    ///         f: &mut core::fmt::Formatter<'_>,
667    ///     ) -> core::fmt::Result {
668    ///         use core::fmt::Write as _;
669    ///
670    ///         if f.alternate() {
671    ///             return core::fmt::Debug::fmt(error, f);
672    ///         }
673    ///
674    ///         write!(f, "{}", error)?;
675    ///
676    ///         if let Some(cause) = error.source() {
677    ///             write!(f, "\n\nCaused by:")?;
678    ///             let multiple = cause.source().is_some();
679    ///
680    ///             for (n, error) in Chain::new(cause).enumerate() {
681    ///                 writeln!(f)?;
682    ///                 if multiple {
683    ///                     write!(indented(f).ind(n), "{}", error)?;
684    ///                 } else {
685    ///                     write!(indented(f), "{}", error)?;
686    ///                 }
687    ///             }
688    ///         }
689    ///
690    ///         let backtrace = &self.backtrace;
691    ///         write!(f, "\n\nStack backtrace:\n{:?}", backtrace)?;
692    ///
693    ///         Ok(())
694    ///     }
695    /// }
696    /// ```
697    fn debug(
698        &self,
699        error: &(dyn StdError + 'static),
700        f: &mut core::fmt::Formatter<'_>,
701    ) -> core::fmt::Result;
702
703    /// Override for the `Display` format
704    fn display(
705        &self,
706        error: &(dyn StdError + 'static),
707        f: &mut core::fmt::Formatter<'_>,
708    ) -> core::fmt::Result {
709        write!(f, "{}", error)?;
710
711        if f.alternate() {
712            for cause in crate::chain::Chain::new(error).skip(1) {
713                write!(f, ": {}", cause)?;
714            }
715        }
716
717        Result::Ok(())
718    }
719
720    /// Store the location of the caller who constructed this error report
721    #[allow(unused_variables)]
722    fn track_caller(&mut self, location: &'static std::panic::Location<'static>) {}
723}
724
725/// The default provided error report handler for `eyre::Report`.
726///
727/// On nightly this supports conditionally capturing a `std::backtrace::Backtrace` if the source
728/// error did not already capture one.
729#[allow(dead_code)]
730pub struct DefaultHandler {
731    backtrace: Option<Backtrace>,
732    #[cfg(track_caller)]
733    location: Option<&'static std::panic::Location<'static>>,
734}
735
736impl DefaultHandler {
737    /// Manual hook which constructs `DefaultHandler`s.
738    ///
739    /// # Details
740    ///
741    /// When supplied to the `set_hook` function, `default_with` will cause `eyre::Report` to use
742    /// `DefaultHandler` as the error report handler.
743    ///
744    /// If the `auto-install` feature is enabled, and a user-provided hook for constructing
745    /// `EyreHandlers` was not installed using `set_hook`, `DefaultHandler::default_with`
746    /// is automatically installed as the hook.
747    ///
748    /// # Example
749    ///
750    /// ```rust,should_panic
751    /// use eyre::{DefaultHandler, eyre, InstallError, Result, set_hook};
752    ///
753    /// fn main() -> Result<()> {
754    ///     install_default().expect("default handler inexplicably already installed");
755    ///     Err(eyre!("hello from default error city!"))
756    /// }
757    ///
758    /// fn install_default() -> Result<(), InstallError> {
759    ///     set_hook(Box::new(DefaultHandler::default_with))
760    /// }
761    ///
762    /// ```
763    #[allow(unused_variables)]
764    #[cfg_attr(not(feature = "auto-install"), allow(dead_code))]
765    pub fn default_with(error: &(dyn StdError + 'static)) -> Box<dyn EyreHandler> {
766        let backtrace = backtrace_if_absent!(error);
767
768        Box::new(Self {
769            backtrace,
770            #[cfg(track_caller)]
771            location: None,
772        })
773    }
774}
775
776impl core::fmt::Debug for DefaultHandler {
777    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
778        f.debug_struct("DefaultHandler")
779            .field(
780                "backtrace",
781                match &self.backtrace {
782                    Some(_) => &"Some(Backtrace { ... })",
783                    None => &"None",
784                },
785            )
786            .finish()
787    }
788}
789
790impl EyreHandler for DefaultHandler {
791    fn debug(
792        &self,
793        error: &(dyn StdError + 'static),
794        f: &mut core::fmt::Formatter<'_>,
795    ) -> core::fmt::Result {
796        use core::fmt::Write as _;
797
798        if f.alternate() {
799            return core::fmt::Debug::fmt(error, f);
800        }
801
802        write!(f, "{}", error)?;
803
804        if let Some(cause) = error.source() {
805            write!(f, "\n\nCaused by:")?;
806            let multiple = cause.source().is_some();
807            for (n, error) in crate::chain::Chain::new(cause).enumerate() {
808                writeln!(f)?;
809                if multiple {
810                    write!(indenter::indented(f).ind(n), "{}", error)?;
811                } else {
812                    write!(indenter::indented(f), "{}", error)?;
813                }
814            }
815        }
816
817        #[cfg(all(track_caller, feature = "track-caller"))]
818        {
819            if let Some(location) = self.location {
820                write!(f, "\n\nLocation:\n")?;
821                write!(indenter::indented(f), "{}", location)?;
822            }
823        }
824
825        #[cfg(backtrace)]
826        {
827            use std::backtrace::BacktraceStatus;
828
829            let backtrace = self
830                .backtrace
831                .as_ref()
832                .or_else(|| error.backtrace())
833                .expect("backtrace capture failed");
834            if let BacktraceStatus::Captured = backtrace.status() {
835                write!(f, "\n\nStack backtrace:\n{}", backtrace)?;
836            }
837        }
838
839        Result::Ok(())
840    }
841
842    #[cfg(track_caller)]
843    fn track_caller(&mut self, location: &'static std::panic::Location<'static>) {
844        self.location = Some(location);
845    }
846}
847
848/// Iterator of a chain of source errors.
849///
850/// This type is the iterator returned by [`Report::chain`].
851///
852/// # Example
853///
854/// ```
855/// use eyre::Report;
856/// use std::io;
857///
858/// pub fn underlying_io_error_kind(error: &Report) -> Option<io::ErrorKind> {
859///     for cause in error.chain() {
860///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
861///             return Some(io_error.kind());
862///         }
863///     }
864///     None
865/// }
866/// ```
867#[derive(Clone)]
868#[allow(missing_debug_implementations)]
869pub struct Chain<'a> {
870    state: crate::chain::ChainState<'a>,
871}
872
873/// type alias for `Result<T, Report>`
874///
875/// This is a reasonable return type to use throughout your application but also for `fn main`; if
876/// you do, failures will be printed along with a backtrace if one was captured.
877///
878/// `eyre::Result` may be used with one *or* two type parameters.
879///
880/// ```rust
881/// use eyre::Result;
882///
883/// # const IGNORE: &str = stringify! {
884/// fn demo1() -> Result<T> {...}
885///            // ^ equivalent to std::result::Result<T, eyre::Report>
886///
887/// fn demo2() -> Result<T, OtherError> {...}
888///            // ^ equivalent to std::result::Result<T, OtherError>
889/// # };
890/// ```
891///
892/// # Example
893///
894/// ```
895/// # pub trait Deserialize {}
896/// #
897/// # mod serde_json {
898/// #     use super::Deserialize;
899/// #     use std::io;
900/// #
901/// #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
902/// #         unimplemented!()
903/// #     }
904/// # }
905/// #
906/// # #[derive(Debug)]
907/// # struct ClusterMap;
908/// #
909/// # impl Deserialize for ClusterMap {}
910/// #
911/// use eyre::Result;
912///
913/// fn main() -> Result<()> {
914///     # return Ok(());
915///     let config = std::fs::read_to_string("cluster.json")?;
916///     let map: ClusterMap = serde_json::from_str(&config)?;
917///     println!("cluster info: {:#?}", map);
918///     Ok(())
919/// }
920/// ```
921pub type Result<T, E = Report> = core::result::Result<T, E>;
922
923/// Provides the `wrap_err` method for `Result`.
924///
925/// This trait is sealed and cannot be implemented for types outside of
926/// `eyre`.
927///
928/// # Example
929///
930/// ```
931/// use eyre::{WrapErr, Result};
932/// use std::fs;
933/// use std::path::PathBuf;
934///
935/// pub struct ImportantThing {
936///     path: PathBuf,
937/// }
938///
939/// impl ImportantThing {
940///     # const IGNORE: &'static str = stringify! {
941///     pub fn detach(&mut self) -> Result<()> {...}
942///     # };
943///     # fn detach(&mut self) -> Result<()> {
944///     #     unimplemented!()
945///     # }
946/// }
947///
948/// pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> {
949///     it.detach().wrap_err("Failed to detach the important thing")?;
950///
951///     let path = &it.path;
952///     let content = fs::read(path)
953///         .wrap_err_with(|| format!("Failed to read instrs from {}", path.display()))?;
954///
955///     Ok(content)
956/// }
957/// ```
958///
959/// When printed, the outermost error would be printed first and the lower
960/// level underlying causes would be enumerated below.
961///
962/// ```console
963/// Error: Failed to read instrs from ./path/to/instrs.json
964///
965/// Caused by:
966///     No such file or directory (os error 2)
967/// ```
968///
969/// # Wrapping Types That Don't impl `Error` (e.g. `&str` and `Box<dyn Error>`)
970///
971/// Due to restrictions for coherence `Report` cannot impl `From` for types that don't impl
972/// `Error`. Attempts to do so will give "this type might implement Error in the future" as an
973/// error. As such, `wrap_err`, which uses `From` under the hood, cannot be used to wrap these
974/// types. Instead we encourage you to use the combinators provided for `Result` in `std`/`core`.
975///
976/// For example, instead of this:
977///
978/// ```rust,compile_fail
979/// use std::error::Error;
980/// use eyre::{WrapErr, Report};
981///
982/// fn wrap_example(err: Result<(), Box<dyn Error + Send + Sync + 'static>>) -> Result<(), Report> {
983///     err.wrap_err("saw a downstream error")
984/// }
985/// ```
986///
987/// We encourage you to write this:
988///
989/// ```rust
990/// use std::error::Error;
991/// use eyre::{WrapErr, Report, eyre};
992///
993/// fn wrap_example(err: Result<(), Box<dyn Error + Send + Sync + 'static>>) -> Result<(), Report> {
994///     err.map_err(|e| eyre!(e)).wrap_err("saw a downstream error")
995/// }
996/// ```
997///
998/// # Effect on downcasting
999///
1000/// After attaching a message of type `D` onto an error of type `E`, the resulting
1001/// `eyre::Report` may be downcast to `D` **or** to `E`.
1002///
1003/// That is, in codebases that rely on downcasting, Eyre's wrap_err supports
1004/// both of the following use cases:
1005///
1006///   - **Attaching messages whose type is insignificant onto errors whose type
1007///     is used in downcasts.**
1008///
1009///     In other error libraries whose wrap_err is not designed this way, it can
1010///     be risky to introduce messages to existing code because new message might
1011///     break existing working downcasts. In Eyre, any downcast that worked
1012///     before adding the message will continue to work after you add a message, so
1013///     you should freely wrap errors wherever it would be helpful.
1014///
1015///     ```
1016///     # use eyre::bail;
1017///     # use thiserror::Error;
1018///     #
1019///     # #[derive(Error, Debug)]
1020///     # #[error("???")]
1021///     # struct SuspiciousError;
1022///     #
1023///     # fn helper() -> Result<()> {
1024///     #     bail!(SuspiciousError);
1025///     # }
1026///     #
1027///     use eyre::{WrapErr, Result};
1028///
1029///     fn do_it() -> Result<()> {
1030///         helper().wrap_err("Failed to complete the work")?;
1031///         # const IGNORE: &str = stringify! {
1032///         ...
1033///         # };
1034///         # unreachable!()
1035///     }
1036///
1037///     fn main() {
1038///         # #[cfg(not(feature = "auto-install"))]
1039///         # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
1040///         let err = do_it().unwrap_err();
1041///         if let Some(e) = err.downcast_ref::<SuspiciousError>() {
1042///             // If helper() returned SuspiciousError, this downcast will
1043///             // correctly succeed even with the message in between.
1044///             # return;
1045///         }
1046///         # panic!("expected downcast to succeed");
1047///     }
1048///     ```
1049///
1050///   - **Attaching message whose type is used in downcasts onto errors whose
1051///     type is insignificant.**
1052///
1053///     Some codebases prefer to use machine-readable messages to categorize
1054///     lower level errors in a way that will be actionable to higher levels of
1055///     the application.
1056///
1057///     ```
1058///     # use eyre::bail;
1059///     # use thiserror::Error;
1060///     #
1061///     # #[derive(Error, Debug)]
1062///     # #[error("???")]
1063///     # struct HelperFailed;
1064///     #
1065///     # fn helper() -> Result<()> {
1066///     #     bail!("no such file or directory");
1067///     # }
1068///     #
1069///     use eyre::{WrapErr, Result};
1070///
1071///     fn do_it() -> Result<()> {
1072///         helper().wrap_err(HelperFailed)?;
1073///         # const IGNORE: &str = stringify! {
1074///         ...
1075///         # };
1076///         # unreachable!()
1077///     }
1078///
1079///     fn main() {
1080///         # #[cfg(not(feature = "auto-install"))]
1081///         # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
1082///         let err = do_it().unwrap_err();
1083///         if let Some(e) = err.downcast_ref::<HelperFailed>() {
1084///             // If helper failed, this downcast will succeed because
1085///             // HelperFailed is the message that has been attached to
1086///             // that error.
1087///             # return;
1088///         }
1089///         # panic!("expected downcast to succeed");
1090///     }
1091///     ```
1092///
1093/// # `wrap_err` vs `wrap_err_with`
1094///
1095/// `wrap_err` incurs a runtime cost even in the non-error case because it requires eagerly
1096/// constructing the error object. `wrap_err_with` avoids this cost through lazy evaluation. This
1097/// cost is proportional to the cost of the currently installed [`EyreHandler`]'s creation step.
1098/// `wrap_err` is useful in cases where an constructed error object already exists.
1099pub trait WrapErr<T, E>: context::private::Sealed {
1100    /// Wrap the error value with a new adhoc error
1101    #[cfg_attr(track_caller, track_caller)]
1102    fn wrap_err<D>(self, msg: D) -> Result<T, Report>
1103    where
1104        D: Display + Send + Sync + 'static;
1105
1106    /// Wrap the error value with a new adhoc error that is evaluated lazily
1107    /// only once an error does occur.
1108    #[cfg_attr(track_caller, track_caller)]
1109    fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report>
1110    where
1111        D: Display + Send + Sync + 'static,
1112        F: FnOnce() -> D;
1113
1114    /// Compatibility re-export of wrap_err for interop with `anyhow`
1115    #[cfg_attr(track_caller, track_caller)]
1116    fn context<D>(self, msg: D) -> Result<T, Report>
1117    where
1118        D: Display + Send + Sync + 'static;
1119
1120    /// Compatibility re-export of wrap_err_with for interop with `anyhow`
1121    #[cfg_attr(track_caller, track_caller)]
1122    fn with_context<D, F>(self, f: F) -> Result<T, Report>
1123    where
1124        D: Display + Send + Sync + 'static,
1125        F: FnOnce() -> D;
1126}
1127
1128/// Provides the [`ok_or_eyre`][OptionExt::ok_or_eyre] method for [`Option`].
1129///
1130/// This trait is sealed and cannot be implemented for types outside of
1131/// `eyre`.
1132///
1133/// # Example
1134///
1135/// ```
1136/// # #[cfg(not(feature = "auto-install"))]
1137/// # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
1138/// use eyre::OptionExt;
1139///
1140/// let option: Option<()> = None;
1141///
1142/// let result = option.ok_or_eyre("static str error");
1143///
1144/// assert_eq!(result.unwrap_err().to_string(), "static str error");
1145/// ```
1146///
1147/// # `ok_or_eyre` vs `ok_or_else`
1148///
1149/// If string interpolation is required for the generated [report][Report],
1150/// use [`ok_or_else`][Option::ok_or_else] instead,
1151/// invoking [`eyre!`] to perform string interpolation:
1152///
1153/// ```
1154/// # #[cfg(not(feature = "auto-install"))]
1155/// # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
1156/// use eyre::eyre;
1157///
1158/// let option: Option<()> = None;
1159///
1160/// let result = option.ok_or_else(|| eyre!("{} error", "dynamic"));
1161///
1162/// assert_eq!(result.unwrap_err().to_string(), "dynamic error");
1163/// ```
1164///
1165/// `ok_or_eyre` incurs no runtime cost, as the error object
1166/// is constructed from the provided static argument
1167/// only in the `None` case.
1168pub trait OptionExt<T>: context::private::Sealed {
1169    /// Transform the [`Option<T>`] into a [`Result<T, E>`],
1170    /// mapping [`Some(v)`][Option::Some] to [`Ok(v)`][Result::Ok]
1171    /// and [`None`] to [`Report`].
1172    ///
1173    /// `ok_or_eyre` allows for eyre [`Report`] error objects
1174    /// to be lazily created from static messages in the `None` case.
1175    ///
1176    /// For dynamic error messages, use [`ok_or_else`][Option::ok_or_else],
1177    /// invoking [`eyre!`] in the closure to perform string interpolation.
1178    fn ok_or_eyre<M>(self, message: M) -> crate::Result<T>
1179    where
1180        M: Debug + Display + Send + Sync + 'static;
1181}
1182
1183/// Provides the `context` method for `Option` when porting from `anyhow`
1184///
1185/// This trait is sealed and cannot be implemented for types outside of
1186/// `eyre`.
1187///
1188/// ## Why Doesn't `Eyre` impl `WrapErr` for `Option`?
1189///
1190/// `eyre` doesn't impl `WrapErr` for `Option` because `wrap_err` implies that you're creating a
1191/// new error that saves the previous error as its `source`. Calling `wrap_err` on an `Option` is
1192/// meaningless because there is no source error. `anyhow` avoids this issue by using a different
1193/// mental model where you're adding "context" to an error, though this not a mental model for
1194/// error handling that `eyre` agrees with.
1195///
1196/// Instead, `eyre` encourages users to think of each error as distinct, where the previous error
1197/// is the context being saved by the new error, which is backwards compared to anyhow's model. In
1198/// this model you're encouraged to use combinators provided by `std` for `Option` to convert an
1199/// option to a `Result`
1200///
1201/// # Example
1202///
1203/// Instead of:
1204///
1205/// ```rust
1206/// use eyre::ContextCompat;
1207///
1208/// fn get_thing(mut things: impl Iterator<Item = u32>) -> eyre::Result<u32> {
1209///     things
1210///         .find(|&thing| thing == 42)
1211///         .context("the thing wasnt in the list")
1212/// }
1213/// ```
1214///
1215/// We encourage you to use this:
1216///
1217/// ```rust
1218/// use eyre::eyre;
1219///
1220/// fn get_thing(mut things: impl Iterator<Item = u32>) -> eyre::Result<u32> {
1221///     things
1222///         .find(|&thing| thing == 42)
1223///         .ok_or_else(|| eyre!("the thing wasnt in the list"))
1224/// }
1225/// ```
1226pub trait ContextCompat<T>: context::private::Sealed {
1227    /// Compatibility version of `wrap_err` for creating new errors with new source on `Option`
1228    /// when porting from `anyhow`
1229    #[cfg_attr(track_caller, track_caller)]
1230    fn context<D>(self, msg: D) -> Result<T, Report>
1231    where
1232        D: Display + Send + Sync + 'static;
1233
1234    /// Compatibility version of `wrap_err_with` for creating new errors with new source on `Option`
1235    /// when porting from `anyhow`
1236    #[cfg_attr(track_caller, track_caller)]
1237    fn with_context<D, F>(self, f: F) -> Result<T, Report>
1238    where
1239        D: Display + Send + Sync + 'static,
1240        F: FnOnce() -> D;
1241
1242    /// Compatibility re-export of `context` for porting from `anyhow` to `eyre`
1243    #[cfg_attr(track_caller, track_caller)]
1244    fn wrap_err<D>(self, msg: D) -> Result<T, Report>
1245    where
1246        D: Display + Send + Sync + 'static;
1247
1248    /// Compatibility re-export of `with_context` for porting from `anyhow` to `eyre`
1249    #[cfg_attr(track_caller, track_caller)]
1250    fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report>
1251    where
1252        D: Display + Send + Sync + 'static,
1253        F: FnOnce() -> D;
1254}
1255
1256/// Equivalent to Ok::<_, eyre::Error>(value).
1257///
1258/// This simplifies creation of an eyre::Result in places where type inference
1259/// cannot deduce the `E` type of the result &mdash; without needing to write
1260/// `Ok::<_, eyre::Error>(value)`.
1261///
1262/// One might think that `eyre::Result::Ok(value)` would work in such cases
1263/// but it does not.
1264///
1265/// ```console
1266/// error[E0282]: type annotations needed for `std::result::Result<i32, E>`
1267///   --> src/main.rs:11:13
1268///    |
1269/// 11 |     let _ = eyre::Result::Ok(1);
1270///    |         -   ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the enum `Result`
1271///    |         |
1272///    |         consider giving this pattern the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified
1273/// ```
1274#[allow(non_snake_case)]
1275pub fn Ok<T>(t: T) -> Result<T> {
1276    Result::Ok(t)
1277}
1278
1279// Not public API. Referenced by macro-generated code.
1280#[doc(hidden)]
1281pub mod private {
1282    use crate::Report;
1283    use alloc::fmt;
1284    use core::fmt::{Arguments, Debug, Display};
1285
1286    pub use alloc::format;
1287    pub use core::format_args;
1288    pub use core::result::Result::Err;
1289
1290    #[doc(hidden)]
1291    pub mod kind {
1292        pub use crate::kind::{AdhocKind, TraitKind};
1293
1294        pub use crate::kind::BoxedKind;
1295    }
1296
1297    #[cfg_attr(track_caller, track_caller)]
1298    pub fn new_adhoc<M>(message: M) -> Report
1299    where
1300        M: Display + Debug + Send + Sync + 'static,
1301    {
1302        Report::from_adhoc(message)
1303    }
1304
1305    #[doc(hidden)]
1306    #[cold]
1307    #[cfg_attr(track_caller, track_caller)]
1308    pub fn format_err(args: Arguments<'_>) -> Report {
1309        #[cfg(eyre_no_fmt_arguments_as_str)]
1310        let fmt_arguments_as_str: Option<&str> = None;
1311        #[cfg(not(eyre_no_fmt_arguments_as_str))]
1312        let fmt_arguments_as_str = args.as_str();
1313
1314        if let Some(message) = fmt_arguments_as_str {
1315            // eyre!("literal"), can downcast to &'static str
1316            Report::msg(message)
1317        } else {
1318            // eyre!("interpolate {var}"), can downcast to String
1319            Report::msg(fmt::format(args))
1320        }
1321    }
1322}