1 #![doc = include_str!("../../core/src/error.md")]
2 #![stable(feature = "rust1", since = "1.0.0")]
7 use crate::backtrace::Backtrace;
8 use crate::fmt::{self, Write};
10 #[stable(feature = "rust1", since = "1.0.0")]
11 pub use core::error::Error;
14 // This is a hack to prevent `type_id` from being overridden by `Error`
15 // implementations, since that can enable unsound downcasting.
16 #[unstable(feature = "error_type_id", issue = "60784")]
21 /// An error reporter that prints an error and its sources.
23 /// Report also exposes configuration options for formatting the error sources, either entirely on a
24 /// single line, or in multi-line format with each source on a new line.
26 /// `Report` only requires that the wrapped error implement `Error`. It doesn't require that the
27 /// wrapped error be `Send`, `Sync`, or `'static`.
32 /// #![feature(error_reporter)]
33 /// use std::error::{Error, Report};
37 /// struct SuperError {
38 /// source: SuperErrorSideKick,
41 /// impl fmt::Display for SuperError {
42 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 /// write!(f, "SuperError is here!")
47 /// impl Error for SuperError {
48 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
49 /// Some(&self.source)
54 /// struct SuperErrorSideKick;
56 /// impl fmt::Display for SuperErrorSideKick {
57 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 /// write!(f, "SuperErrorSideKick is here!")
62 /// impl Error for SuperErrorSideKick {}
64 /// fn get_super_error() -> Result<(), SuperError> {
65 /// Err(SuperError { source: SuperErrorSideKick })
69 /// match get_super_error() {
70 /// Err(e) => println!("Error: {}", Report::new(e)),
71 /// _ => println!("No error"),
76 /// This example produces the following output:
79 /// Error: SuperError is here!: SuperErrorSideKick is here!
82 /// ## Output consistency
84 /// Report prints the same output via `Display` and `Debug`, so it works well with
85 /// [`Result::unwrap`]/[`Result::expect`] which print their `Err` variant via `Debug`:
88 /// #![feature(error_reporter)]
89 /// use std::error::Report;
90 /// # use std::error::Error;
92 /// # #[derive(Debug)]
93 /// # struct SuperError {
94 /// # source: SuperErrorSideKick,
96 /// # impl fmt::Display for SuperError {
97 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 /// # write!(f, "SuperError is here!")
101 /// # impl Error for SuperError {
102 /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
103 /// # Some(&self.source)
106 /// # #[derive(Debug)]
107 /// # struct SuperErrorSideKick;
108 /// # impl fmt::Display for SuperErrorSideKick {
109 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 /// # write!(f, "SuperErrorSideKick is here!")
113 /// # impl Error for SuperErrorSideKick {}
114 /// # fn get_super_error() -> Result<(), SuperError> {
115 /// # Err(SuperError { source: SuperErrorSideKick })
118 /// get_super_error().map_err(Report::new).unwrap();
121 /// This example produces the following output:
124 /// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!', src/error.rs:34:40
125 /// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
128 /// ## Return from `main`
130 /// `Report` also implements `From` for all types that implement [`Error`]; this when combined with
131 /// the `Debug` output means `Report` is an ideal starting place for formatting errors returned
135 /// #![feature(error_reporter)]
136 /// use std::error::Report;
137 /// # use std::error::Error;
139 /// # #[derive(Debug)]
140 /// # struct SuperError {
141 /// # source: SuperErrorSideKick,
143 /// # impl fmt::Display for SuperError {
144 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 /// # write!(f, "SuperError is here!")
148 /// # impl Error for SuperError {
149 /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
150 /// # Some(&self.source)
153 /// # #[derive(Debug)]
154 /// # struct SuperErrorSideKick;
155 /// # impl fmt::Display for SuperErrorSideKick {
156 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 /// # write!(f, "SuperErrorSideKick is here!")
160 /// # impl Error for SuperErrorSideKick {}
161 /// # fn get_super_error() -> Result<(), SuperError> {
162 /// # Err(SuperError { source: SuperErrorSideKick })
165 /// fn main() -> Result<(), Report<SuperError>> {
166 /// get_super_error()?;
171 /// This example produces the following output:
174 /// Error: SuperError is here!: SuperErrorSideKick is here!
177 /// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line
178 /// output format. If you want to make sure your `Report`s are pretty printed and include backtrace
179 /// you will need to manually convert and enable those flags.
182 /// #![feature(error_reporter)]
183 /// use std::error::Report;
184 /// # use std::error::Error;
186 /// # #[derive(Debug)]
187 /// # struct SuperError {
188 /// # source: SuperErrorSideKick,
190 /// # impl fmt::Display for SuperError {
191 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 /// # write!(f, "SuperError is here!")
195 /// # impl Error for SuperError {
196 /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
197 /// # Some(&self.source)
200 /// # #[derive(Debug)]
201 /// # struct SuperErrorSideKick;
202 /// # impl fmt::Display for SuperErrorSideKick {
203 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 /// # write!(f, "SuperErrorSideKick is here!")
207 /// # impl Error for SuperErrorSideKick {}
208 /// # fn get_super_error() -> Result<(), SuperError> {
209 /// # Err(SuperError { source: SuperErrorSideKick })
212 /// fn main() -> Result<(), Report<SuperError>> {
213 /// get_super_error()
214 /// .map_err(Report::from)
215 /// .map_err(|r| r.pretty(true).show_backtrace(true))?;
220 /// This example produces the following output:
223 /// Error: SuperError is here!
226 /// SuperErrorSideKick is here!
228 #[unstable(feature = "error_reporter", issue = "90172")]
229 pub struct Report<E = Box<dyn Error>> {
230 /// The error being reported.
232 /// Whether a backtrace should be included as part of the report.
233 show_backtrace: bool,
234 /// Whether the report should be pretty-printed.
242 /// Create a new `Report` from an input error.
243 #[unstable(feature = "error_reporter", issue = "90172")]
244 pub fn new(error: E) -> Report<E> {
250 /// Enable pretty-printing the report across multiple lines.
255 /// #![feature(error_reporter)]
256 /// use std::error::Report;
257 /// # use std::error::Error;
259 /// # #[derive(Debug)]
260 /// # struct SuperError {
261 /// # source: SuperErrorSideKick,
263 /// # impl fmt::Display for SuperError {
264 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 /// # write!(f, "SuperError is here!")
268 /// # impl Error for SuperError {
269 /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
270 /// # Some(&self.source)
273 /// # #[derive(Debug)]
274 /// # struct SuperErrorSideKick;
275 /// # impl fmt::Display for SuperErrorSideKick {
276 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 /// # write!(f, "SuperErrorSideKick is here!")
280 /// # impl Error for SuperErrorSideKick {}
282 /// let error = SuperError { source: SuperErrorSideKick };
283 /// let report = Report::new(error).pretty(true);
284 /// eprintln!("Error: {report:?}");
287 /// This example produces the following output:
290 /// Error: SuperError is here!
293 /// SuperErrorSideKick is here!
296 /// When there are multiple source errors the causes will be numbered in order of iteration
297 /// starting from the outermost error.
300 /// #![feature(error_reporter)]
301 /// use std::error::Report;
302 /// # use std::error::Error;
304 /// # #[derive(Debug)]
305 /// # struct SuperError {
306 /// # source: SuperErrorSideKick,
308 /// # impl fmt::Display for SuperError {
309 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310 /// # write!(f, "SuperError is here!")
313 /// # impl Error for SuperError {
314 /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
315 /// # Some(&self.source)
318 /// # #[derive(Debug)]
319 /// # struct SuperErrorSideKick {
320 /// # source: SuperErrorSideKickSideKick,
322 /// # impl fmt::Display for SuperErrorSideKick {
323 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
324 /// # write!(f, "SuperErrorSideKick is here!")
327 /// # impl Error for SuperErrorSideKick {
328 /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
329 /// # Some(&self.source)
332 /// # #[derive(Debug)]
333 /// # struct SuperErrorSideKickSideKick;
334 /// # impl fmt::Display for SuperErrorSideKickSideKick {
335 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336 /// # write!(f, "SuperErrorSideKickSideKick is here!")
339 /// # impl Error for SuperErrorSideKickSideKick { }
341 /// let source = SuperErrorSideKickSideKick;
342 /// let source = SuperErrorSideKick { source };
343 /// let error = SuperError { source };
344 /// let report = Report::new(error).pretty(true);
345 /// eprintln!("Error: {report:?}");
348 /// This example produces the following output:
351 /// Error: SuperError is here!
354 /// 0: SuperErrorSideKick is here!
355 /// 1: SuperErrorSideKickSideKick is here!
357 #[unstable(feature = "error_reporter", issue = "90172")]
358 pub fn pretty(mut self, pretty: bool) -> Self {
359 self.pretty = pretty;
363 /// Display backtrace if available when using pretty output format.
367 /// **Note**: Report will search for the first `Backtrace` it can find starting from the
368 /// outermost error. In this example it will display the backtrace from the second error in the
369 /// sources, `SuperErrorSideKick`.
372 /// #![feature(error_reporter)]
373 /// #![feature(provide_any)]
374 /// #![feature(error_generic_member_access)]
375 /// # use std::error::Error;
377 /// use std::any::Demand;
378 /// use std::error::Report;
379 /// use std::backtrace::Backtrace;
381 /// # #[derive(Debug)]
382 /// # struct SuperError {
383 /// # source: SuperErrorSideKick,
385 /// # impl fmt::Display for SuperError {
386 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387 /// # write!(f, "SuperError is here!")
390 /// # impl Error for SuperError {
391 /// # fn source(&self) -> Option<&(dyn Error + 'static)> {
392 /// # Some(&self.source)
396 /// struct SuperErrorSideKick {
397 /// backtrace: Backtrace,
400 /// impl SuperErrorSideKick {
401 /// fn new() -> SuperErrorSideKick {
402 /// SuperErrorSideKick { backtrace: Backtrace::force_capture() }
406 /// impl Error for SuperErrorSideKick {
407 /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
408 /// demand.provide_ref::<Backtrace>(&self.backtrace);
412 /// // The rest of the example is unchanged ...
413 /// # impl fmt::Display for SuperErrorSideKick {
414 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415 /// # write!(f, "SuperErrorSideKick is here!")
419 /// let source = SuperErrorSideKick::new();
420 /// let error = SuperError { source };
421 /// let report = Report::new(error).pretty(true).show_backtrace(true);
422 /// eprintln!("Error: {report:?}");
425 /// This example produces something similar to the following output:
428 /// Error: SuperError is here!
431 /// SuperErrorSideKick is here!
434 /// 0: rust_out::main::_doctest_main_src_error_rs_1158_0::SuperErrorSideKick::new
435 /// 1: rust_out::main::_doctest_main_src_error_rs_1158_0
436 /// 2: rust_out::main
437 /// 3: core::ops::function::FnOnce::call_once
438 /// 4: std::sys_common::backtrace::__rust_begin_short_backtrace
439 /// 5: std::rt::lang_start::{{closure}}
440 /// 6: std::panicking::try
441 /// 7: std::rt::lang_start_internal
442 /// 8: std::rt::lang_start
444 /// 10: __libc_start_main
447 #[unstable(feature = "error_reporter", issue = "90172")]
448 pub fn show_backtrace(mut self, show_backtrace: bool) -> Self {
449 self.show_backtrace = show_backtrace;
458 fn backtrace(&self) -> Option<&Backtrace> {
459 // have to grab the backtrace on the first error directly since that error may not be
461 let backtrace = (&self.error as &dyn Error).request_ref();
462 let backtrace = backtrace.or_else(|| {
465 .map(|source| source.sources().find_map(|source| source.request_ref()))
471 /// Format the report as a single line.
472 #[unstable(feature = "error_reporter", issue = "90172")]
473 fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
474 write!(f, "{}", self.error)?;
476 let sources = self.error.source().into_iter().flat_map(<dyn Error>::sources);
478 for cause in sources {
479 write!(f, ": {cause}")?;
485 /// Format the report as multiple lines, with each error cause on its own line.
486 #[unstable(feature = "error_reporter", issue = "90172")]
487 fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
488 let error = &self.error;
490 write!(f, "{error}")?;
492 if let Some(cause) = error.source() {
493 write!(f, "\n\nCaused by:")?;
495 let multiple = cause.source().is_some();
497 for (ind, error) in cause.sources().enumerate() {
499 let mut indented = Indented { inner: f };
501 write!(indented, "{ind: >4}: {error}")?;
503 write!(indented, " {error}")?;
508 if self.show_backtrace {
509 let backtrace = self.backtrace();
511 if let Some(backtrace) = backtrace {
512 let backtrace = backtrace.to_string();
514 f.write_str("\n\nStack backtrace:\n")?;
515 f.write_str(backtrace.trim_end())?;
523 #[unstable(feature = "error_reporter", issue = "90172")]
524 impl<E> From<E> for Report<E>
528 fn from(error: E) -> Self {
529 Report { error, show_backtrace: false, pretty: false }
533 #[unstable(feature = "error_reporter", issue = "90172")]
534 impl<E> fmt::Display for Report<E>
538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) }
543 // This type intentionally outputs the same format for `Display` and `Debug`for
544 // situations where you unwrap a `Report` or return it from main.
545 #[unstable(feature = "error_reporter", issue = "90172")]
546 impl<E> fmt::Debug for Report<E>
548 Report<E>: fmt::Display,
550 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551 fmt::Display::fmt(self, f)
555 /// Wrapper type for indenting the inner source.
556 struct Indented<'a, D> {
560 impl<T> Write for Indented<'_, T>
564 fn write_str(&mut self, s: &str) -> fmt::Result {
565 for (i, line) in s.split('\n').enumerate() {
567 self.inner.write_char('\n')?;
568 self.inner.write_str(" ")?;
571 self.inner.write_str(line)?;