|  | #![doc = include_str!("../../core/src/error.md")] | 
|  | #![stable(feature = "rust1", since = "1.0.0")] | 
|  |  | 
|  | #[stable(feature = "rust1", since = "1.0.0")] | 
|  | pub use core::error::Error; | 
|  | #[unstable(feature = "error_generic_member_access", issue = "99301")] | 
|  | pub use core::error::{Request, request_ref, request_value}; | 
|  |  | 
|  | use crate::backtrace::Backtrace; | 
|  | use crate::fmt::{self, Write}; | 
|  |  | 
|  | /// An error reporter that prints an error and its sources. | 
|  | /// | 
|  | /// Report also exposes configuration options for formatting the error sources, either entirely on a | 
|  | /// single line, or in multi-line format with each source on a new line. | 
|  | /// | 
|  | /// `Report` only requires that the wrapped error implement `Error`. It doesn't require that the | 
|  | /// wrapped error be `Send`, `Sync`, or `'static`. | 
|  | /// | 
|  | /// # Examples | 
|  | /// | 
|  | /// ```rust | 
|  | /// #![feature(error_reporter)] | 
|  | /// use std::error::{Error, Report}; | 
|  | /// use std::fmt; | 
|  | /// | 
|  | /// #[derive(Debug)] | 
|  | /// struct SuperError { | 
|  | ///     source: SuperErrorSideKick, | 
|  | /// } | 
|  | /// | 
|  | /// impl fmt::Display for SuperError { | 
|  | ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | ///         write!(f, "SuperError is here!") | 
|  | ///     } | 
|  | /// } | 
|  | /// | 
|  | /// impl Error for SuperError { | 
|  | ///     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | ///         Some(&self.source) | 
|  | ///     } | 
|  | /// } | 
|  | /// | 
|  | /// #[derive(Debug)] | 
|  | /// struct SuperErrorSideKick; | 
|  | /// | 
|  | /// impl fmt::Display for SuperErrorSideKick { | 
|  | ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | ///         write!(f, "SuperErrorSideKick is here!") | 
|  | ///     } | 
|  | /// } | 
|  | /// | 
|  | /// impl Error for SuperErrorSideKick {} | 
|  | /// | 
|  | /// fn get_super_error() -> Result<(), SuperError> { | 
|  | ///     Err(SuperError { source: SuperErrorSideKick }) | 
|  | /// } | 
|  | /// | 
|  | /// fn main() { | 
|  | ///     match get_super_error() { | 
|  | ///         Err(e) => println!("Error: {}", Report::new(e)), | 
|  | ///         _ => println!("No error"), | 
|  | ///     } | 
|  | /// } | 
|  | /// ``` | 
|  | /// | 
|  | /// This example produces the following output: | 
|  | /// | 
|  | /// ```console | 
|  | /// Error: SuperError is here!: SuperErrorSideKick is here! | 
|  | /// ``` | 
|  | /// | 
|  | /// ## Output consistency | 
|  | /// | 
|  | /// Report prints the same output via `Display` and `Debug`, so it works well with | 
|  | /// [`Result::unwrap`]/[`Result::expect`] which print their `Err` variant via `Debug`: | 
|  | /// | 
|  | /// ```should_panic | 
|  | /// #![feature(error_reporter)] | 
|  | /// use std::error::Report; | 
|  | /// # use std::error::Error; | 
|  | /// # use std::fmt; | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperError { | 
|  | /// #     source: SuperErrorSideKick, | 
|  | /// # } | 
|  | /// # impl fmt::Display for SuperError { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperError is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperError { | 
|  | /// #     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | /// #         Some(&self.source) | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperErrorSideKick; | 
|  | /// # impl fmt::Display for SuperErrorSideKick { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperErrorSideKick is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperErrorSideKick {} | 
|  | /// # fn get_super_error() -> Result<(), SuperError> { | 
|  | /// #     Err(SuperError { source: SuperErrorSideKick }) | 
|  | /// # } | 
|  | /// | 
|  | /// get_super_error().map_err(Report::new).unwrap(); | 
|  | /// ``` | 
|  | /// | 
|  | /// This example produces the following output: | 
|  | /// | 
|  | /// ```console | 
|  | /// thread 'main' panicked at src/error.rs:34:40: | 
|  | /// called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here! | 
|  | /// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace | 
|  | /// ``` | 
|  | /// | 
|  | /// ## Return from `main` | 
|  | /// | 
|  | /// `Report` also implements `From` for all types that implement [`Error`]; this when combined with | 
|  | /// the `Debug` output means `Report` is an ideal starting place for formatting errors returned | 
|  | /// from `main`. | 
|  | /// | 
|  | /// ```should_panic | 
|  | /// #![feature(error_reporter)] | 
|  | /// use std::error::Report; | 
|  | /// # use std::error::Error; | 
|  | /// # use std::fmt; | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperError { | 
|  | /// #     source: SuperErrorSideKick, | 
|  | /// # } | 
|  | /// # impl fmt::Display for SuperError { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperError is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperError { | 
|  | /// #     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | /// #         Some(&self.source) | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperErrorSideKick; | 
|  | /// # impl fmt::Display for SuperErrorSideKick { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperErrorSideKick is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperErrorSideKick {} | 
|  | /// # fn get_super_error() -> Result<(), SuperError> { | 
|  | /// #     Err(SuperError { source: SuperErrorSideKick }) | 
|  | /// # } | 
|  | /// | 
|  | /// fn main() -> Result<(), Report<SuperError>> { | 
|  | ///     get_super_error()?; | 
|  | ///     Ok(()) | 
|  | /// } | 
|  | /// ``` | 
|  | /// | 
|  | /// This example produces the following output: | 
|  | /// | 
|  | /// ```console | 
|  | /// Error: SuperError is here!: SuperErrorSideKick is here! | 
|  | /// ``` | 
|  | /// | 
|  | /// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line | 
|  | /// output format. If you want to make sure your `Report`s are pretty printed and include backtrace | 
|  | /// you will need to manually convert and enable those flags. | 
|  | /// | 
|  | /// ```should_panic | 
|  | /// #![feature(error_reporter)] | 
|  | /// use std::error::Report; | 
|  | /// # use std::error::Error; | 
|  | /// # use std::fmt; | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperError { | 
|  | /// #     source: SuperErrorSideKick, | 
|  | /// # } | 
|  | /// # impl fmt::Display for SuperError { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperError is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperError { | 
|  | /// #     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | /// #         Some(&self.source) | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperErrorSideKick; | 
|  | /// # impl fmt::Display for SuperErrorSideKick { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperErrorSideKick is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperErrorSideKick {} | 
|  | /// # fn get_super_error() -> Result<(), SuperError> { | 
|  | /// #     Err(SuperError { source: SuperErrorSideKick }) | 
|  | /// # } | 
|  | /// | 
|  | /// fn main() -> Result<(), Report<SuperError>> { | 
|  | ///     get_super_error() | 
|  | ///         .map_err(Report::from) | 
|  | ///         .map_err(|r| r.pretty(true).show_backtrace(true))?; | 
|  | ///     Ok(()) | 
|  | /// } | 
|  | /// ``` | 
|  | /// | 
|  | /// This example produces the following output: | 
|  | /// | 
|  | /// ```console | 
|  | /// Error: SuperError is here! | 
|  | /// | 
|  | /// Caused by: | 
|  | ///       SuperErrorSideKick is here! | 
|  | /// ``` | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | pub struct Report<E = Box<dyn Error>> { | 
|  | /// The error being reported. | 
|  | error: E, | 
|  | /// Whether a backtrace should be included as part of the report. | 
|  | show_backtrace: bool, | 
|  | /// Whether the report should be pretty-printed. | 
|  | pretty: bool, | 
|  | } | 
|  |  | 
|  | impl<E> Report<E> | 
|  | where | 
|  | Report<E>: From<E>, | 
|  | { | 
|  | /// Creates a new `Report` from an input error. | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | pub fn new(error: E) -> Report<E> { | 
|  | Self::from(error) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<E> Report<E> { | 
|  | /// Enable pretty-printing the report across multiple lines. | 
|  | /// | 
|  | /// # Examples | 
|  | /// | 
|  | /// ```rust | 
|  | /// #![feature(error_reporter)] | 
|  | /// use std::error::Report; | 
|  | /// # use std::error::Error; | 
|  | /// # use std::fmt; | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperError { | 
|  | /// #     source: SuperErrorSideKick, | 
|  | /// # } | 
|  | /// # impl fmt::Display for SuperError { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperError is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperError { | 
|  | /// #     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | /// #         Some(&self.source) | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperErrorSideKick; | 
|  | /// # impl fmt::Display for SuperErrorSideKick { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperErrorSideKick is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperErrorSideKick {} | 
|  | /// | 
|  | /// let error = SuperError { source: SuperErrorSideKick }; | 
|  | /// let report = Report::new(error).pretty(true); | 
|  | /// eprintln!("Error: {report:?}"); | 
|  | /// ``` | 
|  | /// | 
|  | /// This example produces the following output: | 
|  | /// | 
|  | /// ```console | 
|  | /// Error: SuperError is here! | 
|  | /// | 
|  | /// Caused by: | 
|  | ///       SuperErrorSideKick is here! | 
|  | /// ``` | 
|  | /// | 
|  | /// When there are multiple source errors the causes will be numbered in order of iteration | 
|  | /// starting from the outermost error. | 
|  | /// | 
|  | /// ```rust | 
|  | /// #![feature(error_reporter)] | 
|  | /// use std::error::Report; | 
|  | /// # use std::error::Error; | 
|  | /// # use std::fmt; | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperError { | 
|  | /// #     source: SuperErrorSideKick, | 
|  | /// # } | 
|  | /// # impl fmt::Display for SuperError { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperError is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperError { | 
|  | /// #     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | /// #         Some(&self.source) | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperErrorSideKick { | 
|  | /// #     source: SuperErrorSideKickSideKick, | 
|  | /// # } | 
|  | /// # impl fmt::Display for SuperErrorSideKick { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperErrorSideKick is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperErrorSideKick { | 
|  | /// #     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | /// #         Some(&self.source) | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperErrorSideKickSideKick; | 
|  | /// # impl fmt::Display for SuperErrorSideKickSideKick { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperErrorSideKickSideKick is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperErrorSideKickSideKick { } | 
|  | /// | 
|  | /// let source = SuperErrorSideKickSideKick; | 
|  | /// let source = SuperErrorSideKick { source }; | 
|  | /// let error = SuperError { source }; | 
|  | /// let report = Report::new(error).pretty(true); | 
|  | /// eprintln!("Error: {report:?}"); | 
|  | /// ``` | 
|  | /// | 
|  | /// This example produces the following output: | 
|  | /// | 
|  | /// ```console | 
|  | /// Error: SuperError is here! | 
|  | /// | 
|  | /// Caused by: | 
|  | ///    0: SuperErrorSideKick is here! | 
|  | ///    1: SuperErrorSideKickSideKick is here! | 
|  | /// ``` | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | pub fn pretty(mut self, pretty: bool) -> Self { | 
|  | self.pretty = pretty; | 
|  | self | 
|  | } | 
|  |  | 
|  | /// Display backtrace if available when using pretty output format. | 
|  | /// | 
|  | /// # Examples | 
|  | /// | 
|  | /// **Note**: Report will search for the first `Backtrace` it can find starting from the | 
|  | /// outermost error. In this example it will display the backtrace from the second error in the | 
|  | /// sources, `SuperErrorSideKick`. | 
|  | /// | 
|  | /// ```rust | 
|  | /// #![feature(error_reporter)] | 
|  | /// #![feature(error_generic_member_access)] | 
|  | /// # use std::error::Error; | 
|  | /// # use std::fmt; | 
|  | /// use std::error::Request; | 
|  | /// use std::error::Report; | 
|  | /// use std::backtrace::Backtrace; | 
|  | /// | 
|  | /// # #[derive(Debug)] | 
|  | /// # struct SuperError { | 
|  | /// #     source: SuperErrorSideKick, | 
|  | /// # } | 
|  | /// # impl fmt::Display for SuperError { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperError is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// # impl Error for SuperError { | 
|  | /// #     fn source(&self) -> Option<&(dyn Error + 'static)> { | 
|  | /// #         Some(&self.source) | 
|  | /// #     } | 
|  | /// # } | 
|  | /// #[derive(Debug)] | 
|  | /// struct SuperErrorSideKick { | 
|  | ///     backtrace: Backtrace, | 
|  | /// } | 
|  | /// | 
|  | /// impl SuperErrorSideKick { | 
|  | ///     fn new() -> SuperErrorSideKick { | 
|  | ///         SuperErrorSideKick { backtrace: Backtrace::force_capture() } | 
|  | ///     } | 
|  | /// } | 
|  | /// | 
|  | /// impl Error for SuperErrorSideKick { | 
|  | ///     fn provide<'a>(&'a self, request: &mut Request<'a>) { | 
|  | ///         request.provide_ref::<Backtrace>(&self.backtrace); | 
|  | ///     } | 
|  | /// } | 
|  | /// | 
|  | /// // The rest of the example is unchanged ... | 
|  | /// # impl fmt::Display for SuperErrorSideKick { | 
|  | /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | /// #         write!(f, "SuperErrorSideKick is here!") | 
|  | /// #     } | 
|  | /// # } | 
|  | /// | 
|  | /// let source = SuperErrorSideKick::new(); | 
|  | /// let error = SuperError { source }; | 
|  | /// let report = Report::new(error).pretty(true).show_backtrace(true); | 
|  | /// eprintln!("Error: {report:?}"); | 
|  | /// ``` | 
|  | /// | 
|  | /// This example produces something similar to the following output: | 
|  | /// | 
|  | /// ```console | 
|  | /// Error: SuperError is here! | 
|  | /// | 
|  | /// Caused by: | 
|  | ///       SuperErrorSideKick is here! | 
|  | /// | 
|  | /// Stack backtrace: | 
|  | ///    0: rust_out::main::_doctest_main_src_error_rs_1158_0::SuperErrorSideKick::new | 
|  | ///    1: rust_out::main::_doctest_main_src_error_rs_1158_0 | 
|  | ///    2: rust_out::main | 
|  | ///    3: core::ops::function::FnOnce::call_once | 
|  | ///    4: std::sys::backtrace::__rust_begin_short_backtrace | 
|  | ///    5: std::rt::lang_start::{{closure}} | 
|  | ///    6: std::panicking::try | 
|  | ///    7: std::rt::lang_start_internal | 
|  | ///    8: std::rt::lang_start | 
|  | ///    9: main | 
|  | ///   10: __libc_start_main | 
|  | ///   11: _start | 
|  | /// ``` | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | pub fn show_backtrace(mut self, show_backtrace: bool) -> Self { | 
|  | self.show_backtrace = show_backtrace; | 
|  | self | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<E> Report<E> | 
|  | where | 
|  | E: Error, | 
|  | { | 
|  | fn backtrace(&self) -> Option<&Backtrace> { | 
|  | // have to grab the backtrace on the first error directly since that error may not be | 
|  | // 'static | 
|  | let backtrace = request_ref(&self.error); | 
|  | let backtrace = backtrace.or_else(|| { | 
|  | self.error | 
|  | .source() | 
|  | .map(|source| source.sources().find_map(|source| request_ref(source))) | 
|  | .flatten() | 
|  | }); | 
|  | backtrace | 
|  | } | 
|  |  | 
|  | /// Format the report as a single line. | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | write!(f, "{}", self.error)?; | 
|  |  | 
|  | let sources = self.error.source().into_iter().flat_map(<dyn Error>::sources); | 
|  |  | 
|  | for cause in sources { | 
|  | write!(f, ": {cause}")?; | 
|  | } | 
|  |  | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | /// Format the report as multiple lines, with each error cause on its own line. | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | let error = &self.error; | 
|  |  | 
|  | write!(f, "{error}")?; | 
|  |  | 
|  | if let Some(cause) = error.source() { | 
|  | write!(f, "\n\nCaused by:")?; | 
|  |  | 
|  | let multiple = cause.source().is_some(); | 
|  |  | 
|  | for (ind, error) in cause.sources().enumerate() { | 
|  | writeln!(f)?; | 
|  | let mut indented = Indented { inner: f }; | 
|  | if multiple { | 
|  | write!(indented, "{ind: >4}: {error}")?; | 
|  | } else { | 
|  | write!(indented, "      {error}")?; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if self.show_backtrace { | 
|  | if let Some(backtrace) = self.backtrace() { | 
|  | write!(f, "\n\nStack backtrace:\n{}", backtrace.to_string().trim_end())?; | 
|  | } | 
|  | } | 
|  |  | 
|  | Ok(()) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | impl<E> From<E> for Report<E> | 
|  | where | 
|  | E: Error, | 
|  | { | 
|  | fn from(error: E) -> Self { | 
|  | Report { error, show_backtrace: false, pretty: false } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | impl<E> fmt::Display for Report<E> | 
|  | where | 
|  | E: Error, | 
|  | { | 
|  | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) } | 
|  | } | 
|  | } | 
|  |  | 
|  | // This type intentionally outputs the same format for `Display` and `Debug`for | 
|  | // situations where you unwrap a `Report` or return it from main. | 
|  | #[unstable(feature = "error_reporter", issue = "90172")] | 
|  | impl<E> fmt::Debug for Report<E> | 
|  | where | 
|  | Report<E>: fmt::Display, | 
|  | { | 
|  | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
|  | fmt::Display::fmt(self, f) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Wrapper type for indenting the inner source. | 
|  | struct Indented<'a, D> { | 
|  | inner: &'a mut D, | 
|  | } | 
|  |  | 
|  | impl<T> Write for Indented<'_, T> | 
|  | where | 
|  | T: Write, | 
|  | { | 
|  | fn write_str(&mut self, s: &str) -> fmt::Result { | 
|  | for (i, line) in s.split('\n').enumerate() { | 
|  | if i > 0 { | 
|  | self.inner.write_char('\n')?; | 
|  | self.inner.write_str("      ")?; | 
|  | } | 
|  |  | 
|  | self.inner.write_str(line)?; | 
|  | } | 
|  |  | 
|  | Ok(()) | 
|  | } | 
|  | } |