Skip to main content

std/
error.rs

1#![doc = "Interfaces for working with Errors.\n\n# Error Handling In Rust\n\nThe Rust language provides two complementary systems for constructing /\nrepresenting, reporting, propagating, reacting to, and discarding errors.\nThese responsibilities are collectively known as \"error handling.\" The\ncomponents of the first system, the panic runtime and interfaces, are most\ncommonly used to represent bugs that have been detected in your program. The\ncomponents of the second system, `Result`, the error traits, and user\ndefined types, are used to represent anticipated runtime failure modes of\nyour program.\n\n## The Panic Interfaces\n\nThe following are the primary interfaces of the panic system and the\nresponsibilities they cover:\n\n* [`panic!`] and [`panic_any`] (Constructing, Propagated automatically)\n* [`set_hook`], [`take_hook`], and [`PanicHookInfo`] (Reporting)\n* [`#[panic_handler]`][panic-handler] and [`PanicInfo`] (Reporting in no_std)\n* [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating)\n\nThe following are the primary interfaces of the error system and the\nresponsibilities they cover:\n\n* [`Result`] (Propagating, Reacting)\n* The [`Error`] trait (Reporting)\n* User defined types (Constructing / Representing)\n* [`match`] and [`downcast`] (Reacting)\n* The question mark operator ([`?`]) (Propagating)\n* The partially stable [`Try`] traits (Propagating, Constructing)\n* [`Termination`] (Reporting)\n\n## Converting Errors into Panics\n\nThe panic and error systems are not entirely distinct. Often times errors\nthat are anticipated runtime failures in an API might instead represent bugs\nto a caller. For these situations the standard library provides APIs for\nconstructing panics with an `Error` as its source.\n\n* [`Result::unwrap`]\n* [`Result::expect`]\n\nThese functions are equivalent, they either return the inner value if the\n`Result` is `Ok` or panic if the `Result` is `Err` printing the inner error\nas the source. The only difference between them is that with `expect` you\nprovide a panic error message to be printed alongside the source, whereas\n`unwrap` has a default message indicating only that you unwrapped an `Err`.\n\nOf the two, `expect` is generally preferred since its `msg` field allows you\nto convey your intent and assumptions which makes tracking down the source\nof a panic easier. `unwrap` on the other hand can still be a good fit in\nsituations where you can trivially show that a piece of code will never\npanic, such as `\"127.0.0.1\".parse::<std::net::IpAddr>().unwrap()` or early\nprototyping.\n\n# Common Message Styles\n\nThere are two common styles for how people word `expect` messages. Using\nthe message to present information to users encountering a panic\n(\"expect as error message\") or using the message to present information\nto developers debugging the panic (\"expect as precondition\").\n\nIn the former case the expect message is used to describe the error that\nhas occurred which is considered a bug. Consider the following example:\n\n```should_panic\n// Read environment variable, panic if it is not present\nlet path = std::env::var(\"IMPORTANT_PATH\").unwrap();\n```\n\nIn the \"expect as error message\" style we would use expect to describe\nthat the environment variable was not set when it should have been:\n\n```should_panic\nlet path = std::env::var(\"IMPORTANT_PATH\")\n    .expect(\"env variable `IMPORTANT_PATH` is not set\");\n```\n\nIn the \"expect as precondition\" style, we would instead describe the\nreason we _expect_ the `Result` should be `Ok`. With this style we would\nprefer to write:\n\n```should_panic\nlet path = std::env::var(\"IMPORTANT_PATH\")\n    .expect(\"env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`\");\n```\n\nThe \"expect as error message\" style does not work as well with the\ndefault output of the std panic hooks, and often ends up repeating\ninformation that is already communicated by the source error being\nunwrapped:\n\n```text\nthread \'main\' panicked at src/main.rs:4:6:\nenv variable `IMPORTANT_PATH` is not set: NotPresent\n```\n\nIn this example we end up mentioning that an env variable is not set,\nfollowed by our source message that says the env is not present, the\nonly additional information we\'re communicating is the name of the\nenvironment variable being checked.\n\nThe \"expect as precondition\" style instead focuses on source code\nreadability, making it easier to understand what must have gone wrong in\nsituations where panics are being used to represent bugs exclusively.\nAlso, by framing our expect in terms of what \"SHOULD\" have happened to\nprevent the source error, we end up introducing new information that is\nindependent from our source error.\n\n```text\nthread \'main\' panicked at src/main.rs:4:6:\nenv variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`: NotPresent\n```\n\nIn this example we are communicating not only the name of the\nenvironment variable that should have been set, but also an explanation\nfor why it should have been set, and we let the source error display as\na clear contradiction to our expectation.\n\n**Hint**: If you\'re having trouble remembering how to phrase\nexpect-as-precondition style error messages remember to focus on the word\n\"should\" as in \"env variable should be set by blah\" or \"the given binary\nshould be available and executable by the current user\".\n\n[`panic_any`]: ../../std/panic/fn.panic_any.html\n[`PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html\n[`PanicInfo`]: crate::panic::PanicInfo\n[`catch_unwind`]: ../../std/panic/fn.catch_unwind.html\n[`resume_unwind`]: ../../std/panic/fn.resume_unwind.html\n[`downcast`]: crate::error::Error\n[`Termination`]: ../../std/process/trait.Termination.html\n[`Try`]: crate::ops::Try\n[panic hook]: ../../std/panic/fn.set_hook.html\n[`set_hook`]: ../../std/panic/fn.set_hook.html\n[`take_hook`]: ../../std/panic/fn.take_hook.html\n[panic-handler]: <https://doc.rust-lang.org/nomicon/panic-handler.html>\n[`match`]: ../../std/keyword.match.html\n[`?`]: ../../std/result/index.html#the-question-mark-operator-\n"include_str!("../../core/src/error.md")]
2#![stable(feature = "rust1", since = "1.0.0")]
3
4#[stable(feature = "rust1", since = "1.0.0")]
5pub use core::error::Error;
6#[unstable(feature = "error_generic_member_access", issue = "99301")]
7pub use core::error::{Request, request_ref, request_value};
8
9use crate::backtrace::Backtrace;
10use crate::fmt::{self, Write};
11
12/// An error reporter that prints an error and its sources.
13///
14/// Report also exposes configuration options for formatting the error sources, either entirely on a
15/// single line, or in multi-line format with each source on a new line.
16///
17/// `Report` only requires that the wrapped error implement `Error`. It doesn't require that the
18/// wrapped error be `Send`, `Sync`, or `'static`.
19///
20/// # Examples
21///
22/// ```rust
23/// #![feature(error_reporter)]
24/// use std::error::{Error, Report};
25/// use std::fmt;
26///
27/// #[derive(Debug)]
28/// struct SuperError {
29///     source: SuperErrorSideKick,
30/// }
31///
32/// impl fmt::Display for SuperError {
33///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34///         write!(f, "SuperError is here!")
35///     }
36/// }
37///
38/// impl Error for SuperError {
39///     fn source(&self) -> Option<&(dyn Error + 'static)> {
40///         Some(&self.source)
41///     }
42/// }
43///
44/// #[derive(Debug)]
45/// struct SuperErrorSideKick;
46///
47/// impl fmt::Display for SuperErrorSideKick {
48///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49///         write!(f, "SuperErrorSideKick is here!")
50///     }
51/// }
52///
53/// impl Error for SuperErrorSideKick {}
54///
55/// fn get_super_error() -> Result<(), SuperError> {
56///     Err(SuperError { source: SuperErrorSideKick })
57/// }
58///
59/// fn main() {
60///     match get_super_error() {
61///         Err(e) => println!("Error: {}", Report::new(e)),
62///         _ => println!("No error"),
63///     }
64/// }
65/// ```
66///
67/// This example produces the following output:
68///
69/// ```console
70/// Error: SuperError is here!: SuperErrorSideKick is here!
71/// ```
72///
73/// ## Output consistency
74///
75/// Report prints the same output via `Display` and `Debug`, so it works well with
76/// [`Result::unwrap`]/[`Result::expect`] which print their `Err` variant via `Debug`:
77///
78/// ```should_panic
79/// #![feature(error_reporter)]
80/// use std::error::Report;
81/// # use std::error::Error;
82/// # use std::fmt;
83/// # #[derive(Debug)]
84/// # struct SuperError {
85/// #     source: SuperErrorSideKick,
86/// # }
87/// # impl fmt::Display for SuperError {
88/// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89/// #         write!(f, "SuperError is here!")
90/// #     }
91/// # }
92/// # impl Error for SuperError {
93/// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
94/// #         Some(&self.source)
95/// #     }
96/// # }
97/// # #[derive(Debug)]
98/// # struct SuperErrorSideKick;
99/// # impl fmt::Display for SuperErrorSideKick {
100/// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101/// #         write!(f, "SuperErrorSideKick is here!")
102/// #     }
103/// # }
104/// # impl Error for SuperErrorSideKick {}
105/// # fn get_super_error() -> Result<(), SuperError> {
106/// #     Err(SuperError { source: SuperErrorSideKick })
107/// # }
108///
109/// get_super_error().map_err(Report::new).unwrap();
110/// ```
111///
112/// This example produces the following output:
113///
114/// ```console
115/// thread 'main' panicked at src/error.rs:34:40:
116/// called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!
117/// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
118/// ```
119///
120/// ## Return from `main`
121///
122/// `Report` also implements `From` for all types that implement [`Error`]; this when combined with
123/// the `Debug` output means `Report` is an ideal starting place for formatting errors returned
124/// from `main`.
125///
126/// ```should_panic
127/// #![feature(error_reporter)]
128/// use std::error::Report;
129/// # use std::error::Error;
130/// # use std::fmt;
131/// # #[derive(Debug)]
132/// # struct SuperError {
133/// #     source: SuperErrorSideKick,
134/// # }
135/// # impl fmt::Display for SuperError {
136/// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137/// #         write!(f, "SuperError is here!")
138/// #     }
139/// # }
140/// # impl Error for SuperError {
141/// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
142/// #         Some(&self.source)
143/// #     }
144/// # }
145/// # #[derive(Debug)]
146/// # struct SuperErrorSideKick;
147/// # impl fmt::Display for SuperErrorSideKick {
148/// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149/// #         write!(f, "SuperErrorSideKick is here!")
150/// #     }
151/// # }
152/// # impl Error for SuperErrorSideKick {}
153/// # fn get_super_error() -> Result<(), SuperError> {
154/// #     Err(SuperError { source: SuperErrorSideKick })
155/// # }
156///
157/// fn main() -> Result<(), Report<SuperError>> {
158///     get_super_error()?;
159///     Ok(())
160/// }
161/// ```
162///
163/// This example produces the following output:
164///
165/// ```console
166/// Error: SuperError is here!: SuperErrorSideKick is here!
167/// ```
168///
169/// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line
170/// output format. If you want to make sure your `Report`s are pretty printed and include backtrace
171/// you will need to manually convert and enable those flags.
172///
173/// ```should_panic
174/// #![feature(error_reporter)]
175/// use std::error::Report;
176/// # use std::error::Error;
177/// # use std::fmt;
178/// # #[derive(Debug)]
179/// # struct SuperError {
180/// #     source: SuperErrorSideKick,
181/// # }
182/// # impl fmt::Display for SuperError {
183/// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184/// #         write!(f, "SuperError is here!")
185/// #     }
186/// # }
187/// # impl Error for SuperError {
188/// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
189/// #         Some(&self.source)
190/// #     }
191/// # }
192/// # #[derive(Debug)]
193/// # struct SuperErrorSideKick;
194/// # impl fmt::Display for SuperErrorSideKick {
195/// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196/// #         write!(f, "SuperErrorSideKick is here!")
197/// #     }
198/// # }
199/// # impl Error for SuperErrorSideKick {}
200/// # fn get_super_error() -> Result<(), SuperError> {
201/// #     Err(SuperError { source: SuperErrorSideKick })
202/// # }
203///
204/// fn main() -> Result<(), Report<SuperError>> {
205///     get_super_error()
206///         .map_err(Report::from)
207///         .map_err(|r| r.pretty(true).show_backtrace(true))?;
208///     Ok(())
209/// }
210/// ```
211///
212/// This example produces the following output:
213///
214/// ```console
215/// Error: SuperError is here!
216///
217/// Caused by:
218///       SuperErrorSideKick is here!
219/// ```
220#[unstable(feature = "error_reporter", issue = "90172")]
221pub struct Report<E = Box<dyn Error>> {
222    /// The error being reported.
223    error: E,
224    /// Whether a backtrace should be included as part of the report.
225    show_backtrace: bool,
226    /// Whether the report should be pretty-printed.
227    pretty: bool,
228}
229
230impl<E> Report<E>
231where
232    Report<E>: From<E>,
233{
234    /// Creates a new `Report` from an input error.
235    #[unstable(feature = "error_reporter", issue = "90172")]
236    pub fn new(error: E) -> Report<E> {
237        Self::from(error)
238    }
239}
240
241impl<E> Report<E> {
242    /// Enable pretty-printing the report across multiple lines.
243    ///
244    /// # Examples
245    ///
246    /// ```rust
247    /// #![feature(error_reporter)]
248    /// use std::error::Report;
249    /// # use std::error::Error;
250    /// # use std::fmt;
251    /// # #[derive(Debug)]
252    /// # struct SuperError {
253    /// #     source: SuperErrorSideKick,
254    /// # }
255    /// # impl fmt::Display for SuperError {
256    /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257    /// #         write!(f, "SuperError is here!")
258    /// #     }
259    /// # }
260    /// # impl Error for SuperError {
261    /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
262    /// #         Some(&self.source)
263    /// #     }
264    /// # }
265    /// # #[derive(Debug)]
266    /// # struct SuperErrorSideKick;
267    /// # impl fmt::Display for SuperErrorSideKick {
268    /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269    /// #         write!(f, "SuperErrorSideKick is here!")
270    /// #     }
271    /// # }
272    /// # impl Error for SuperErrorSideKick {}
273    ///
274    /// let error = SuperError { source: SuperErrorSideKick };
275    /// let report = Report::new(error).pretty(true);
276    /// eprintln!("Error: {report:?}");
277    /// ```
278    ///
279    /// This example produces the following output:
280    ///
281    /// ```console
282    /// Error: SuperError is here!
283    ///
284    /// Caused by:
285    ///       SuperErrorSideKick is here!
286    /// ```
287    ///
288    /// When there are multiple source errors the causes will be numbered in order of iteration
289    /// starting from the outermost error.
290    ///
291    /// ```rust
292    /// #![feature(error_reporter)]
293    /// use std::error::Report;
294    /// # use std::error::Error;
295    /// # use std::fmt;
296    /// # #[derive(Debug)]
297    /// # struct SuperError {
298    /// #     source: SuperErrorSideKick,
299    /// # }
300    /// # impl fmt::Display for SuperError {
301    /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302    /// #         write!(f, "SuperError is here!")
303    /// #     }
304    /// # }
305    /// # impl Error for SuperError {
306    /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
307    /// #         Some(&self.source)
308    /// #     }
309    /// # }
310    /// # #[derive(Debug)]
311    /// # struct SuperErrorSideKick {
312    /// #     source: SuperErrorSideKickSideKick,
313    /// # }
314    /// # impl fmt::Display for SuperErrorSideKick {
315    /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316    /// #         write!(f, "SuperErrorSideKick is here!")
317    /// #     }
318    /// # }
319    /// # impl Error for SuperErrorSideKick {
320    /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
321    /// #         Some(&self.source)
322    /// #     }
323    /// # }
324    /// # #[derive(Debug)]
325    /// # struct SuperErrorSideKickSideKick;
326    /// # impl fmt::Display for SuperErrorSideKickSideKick {
327    /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328    /// #         write!(f, "SuperErrorSideKickSideKick is here!")
329    /// #     }
330    /// # }
331    /// # impl Error for SuperErrorSideKickSideKick { }
332    ///
333    /// let source = SuperErrorSideKickSideKick;
334    /// let source = SuperErrorSideKick { source };
335    /// let error = SuperError { source };
336    /// let report = Report::new(error).pretty(true);
337    /// eprintln!("Error: {report:?}");
338    /// ```
339    ///
340    /// This example produces the following output:
341    ///
342    /// ```console
343    /// Error: SuperError is here!
344    ///
345    /// Caused by:
346    ///    0: SuperErrorSideKick is here!
347    ///    1: SuperErrorSideKickSideKick is here!
348    /// ```
349    #[unstable(feature = "error_reporter", issue = "90172")]
350    pub fn pretty(mut self, pretty: bool) -> Self {
351        self.pretty = pretty;
352        self
353    }
354
355    /// Display backtrace if available when using pretty output format.
356    ///
357    /// # Examples
358    ///
359    /// **Note**: Report will search for the first `Backtrace` it can find starting from the
360    /// outermost error. In this example it will display the backtrace from the second error in the
361    /// sources, `SuperErrorSideKick`.
362    ///
363    /// ```rust
364    /// #![feature(error_reporter)]
365    /// #![feature(error_generic_member_access)]
366    /// # use std::error::Error;
367    /// # use std::fmt;
368    /// use std::error::Request;
369    /// use std::error::Report;
370    /// use std::backtrace::Backtrace;
371    ///
372    /// # #[derive(Debug)]
373    /// # struct SuperError {
374    /// #     source: SuperErrorSideKick,
375    /// # }
376    /// # impl fmt::Display for SuperError {
377    /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378    /// #         write!(f, "SuperError is here!")
379    /// #     }
380    /// # }
381    /// # impl Error for SuperError {
382    /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
383    /// #         Some(&self.source)
384    /// #     }
385    /// # }
386    /// #[derive(Debug)]
387    /// struct SuperErrorSideKick {
388    ///     backtrace: Backtrace,
389    /// }
390    ///
391    /// impl SuperErrorSideKick {
392    ///     fn new() -> SuperErrorSideKick {
393    ///         SuperErrorSideKick { backtrace: Backtrace::force_capture() }
394    ///     }
395    /// }
396    ///
397    /// impl Error for SuperErrorSideKick {
398    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
399    ///         request.provide_ref::<Backtrace>(&self.backtrace);
400    ///     }
401    /// }
402    ///
403    /// // The rest of the example is unchanged ...
404    /// # impl fmt::Display for SuperErrorSideKick {
405    /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
406    /// #         write!(f, "SuperErrorSideKick is here!")
407    /// #     }
408    /// # }
409    ///
410    /// let source = SuperErrorSideKick::new();
411    /// let error = SuperError { source };
412    /// let report = Report::new(error).pretty(true).show_backtrace(true);
413    /// eprintln!("Error: {report:?}");
414    /// ```
415    ///
416    /// This example produces something similar to the following output:
417    ///
418    /// ```console
419    /// Error: SuperError is here!
420    ///
421    /// Caused by:
422    ///       SuperErrorSideKick is here!
423    ///
424    /// Stack backtrace:
425    ///    0: rust_out::main::_doctest_main_src_error_rs_1158_0::SuperErrorSideKick::new
426    ///    1: rust_out::main::_doctest_main_src_error_rs_1158_0
427    ///    2: rust_out::main
428    ///    3: core::ops::function::FnOnce::call_once
429    ///    4: std::sys::backtrace::__rust_begin_short_backtrace
430    ///    5: std::rt::lang_start::{{closure}}
431    ///    6: std::panicking::try
432    ///    7: std::rt::lang_start_internal
433    ///    8: std::rt::lang_start
434    ///    9: main
435    ///   10: __libc_start_main
436    ///   11: _start
437    /// ```
438    #[unstable(feature = "error_reporter", issue = "90172")]
439    pub fn show_backtrace(mut self, show_backtrace: bool) -> Self {
440        self.show_backtrace = show_backtrace;
441        self
442    }
443}
444
445impl<E> Report<E>
446where
447    E: Error,
448{
449    fn backtrace(&self) -> Option<&Backtrace> {
450        // have to grab the backtrace on the first error directly since that error may not be
451        // 'static
452        let backtrace = request_ref(&self.error);
453        let backtrace = backtrace.or_else(|| {
454            self.error
455                .source()
456                .map(|source| source.sources().find_map(|source| request_ref(source)))
457                .flatten()
458        });
459        backtrace
460    }
461
462    /// Format the report as a single line.
463    #[unstable(feature = "error_reporter", issue = "90172")]
464    fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465        f.write_fmt(format_args!("{0}", self.error))write!(f, "{}", self.error)?;
466
467        let sources = self.error.source().into_iter().flat_map(<dyn Error>::sources);
468
469        for cause in sources {
470            f.write_fmt(format_args!(": {0}", cause))write!(f, ": {cause}")?;
471        }
472
473        Ok(())
474    }
475
476    /// Format the report as multiple lines, with each error cause on its own line.
477    #[unstable(feature = "error_reporter", issue = "90172")]
478    fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
479        let error = &self.error;
480
481        f.write_fmt(format_args!("{0}", error))write!(f, "{error}")?;
482
483        if let Some(cause) = error.source() {
484            f.write_fmt(format_args!("\n\nCaused by:"))write!(f, "\n\nCaused by:")?;
485
486            let multiple = cause.source().is_some();
487
488            for (ind, error) in cause.sources().enumerate() {
489                f.write_fmt(format_args!("\n"))writeln!(f)?;
490                let mut indented = Indented { inner: f };
491                if multiple {
492                    indented.write_fmt(format_args!("{0: >4}: {1}", ind, error))write!(indented, "{ind: >4}: {error}")?;
493                } else {
494                    indented.write_fmt(format_args!("      {0}", error))write!(indented, "      {error}")?;
495                }
496            }
497        }
498
499        if self.show_backtrace {
500            if let Some(backtrace) = self.backtrace() {
501                f.write_fmt(format_args!("\n\nStack backtrace:\n{0}",
        backtrace.to_string().trim_end()))write!(f, "\n\nStack backtrace:\n{}", backtrace.to_string().trim_end())?;
502            }
503        }
504
505        Ok(())
506    }
507}
508
509#[unstable(feature = "error_reporter", issue = "90172")]
510impl<E> From<E> for Report<E>
511where
512    E: Error,
513{
514    fn from(error: E) -> Self {
515        Report { error, show_backtrace: false, pretty: false }
516    }
517}
518
519#[unstable(feature = "error_reporter", issue = "90172")]
520impl<E> fmt::Display for Report<E>
521where
522    E: Error,
523{
524    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
525        if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) }
526    }
527}
528
529// This type intentionally outputs the same format for `Display` and `Debug`for
530// situations where you unwrap a `Report` or return it from main.
531#[unstable(feature = "error_reporter", issue = "90172")]
532impl<E> fmt::Debug for Report<E>
533where
534    Report<E>: fmt::Display,
535{
536    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
537        fmt::Display::fmt(self, f)
538    }
539}
540
541/// Wrapper type for indenting the inner source.
542struct Indented<'a, D> {
543    inner: &'a mut D,
544}
545
546impl<T> Write for Indented<'_, T>
547where
548    T: Write,
549{
550    fn write_str(&mut self, s: &str) -> fmt::Result {
551        for (i, line) in s.split('\n').enumerate() {
552            if i > 0 {
553                self.inner.write_char('\n')?;
554                self.inner.write_str("      ")?;
555            }
556
557            self.inner.write_str(line)?;
558        }
559
560        Ok(())
561    }
562}