]> git.lizzy.rs Git - rust.git/blob - library/std/src/error.rs
Rollup merge of #107470 - kadiwa4:bootstrap_cleanup, r=albertlarsan68
[rust.git] / library / std / src / error.rs
1 #![doc = include_str!("../../core/src/error.md")]
2 #![stable(feature = "rust1", since = "1.0.0")]
3
4 #[cfg(test)]
5 mod tests;
6
7 use crate::backtrace::Backtrace;
8 use crate::fmt::{self, Write};
9
10 #[stable(feature = "rust1", since = "1.0.0")]
11 pub use core::error::Error;
12
13 mod private {
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")]
17     #[derive(Debug)]
18     pub struct Internal;
19 }
20
21 /// An error reporter that prints an error and its sources.
22 ///
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.
25 ///
26 /// `Report` only requires that the wrapped error implement `Error`. It doesn't require that the
27 /// wrapped error be `Send`, `Sync`, or `'static`.
28 ///
29 /// # Examples
30 ///
31 /// ```rust
32 /// #![feature(error_reporter)]
33 /// use std::error::{Error, Report};
34 /// use std::fmt;
35 ///
36 /// #[derive(Debug)]
37 /// struct SuperError {
38 ///     source: SuperErrorSideKick,
39 /// }
40 ///
41 /// impl fmt::Display for SuperError {
42 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 ///         write!(f, "SuperError is here!")
44 ///     }
45 /// }
46 ///
47 /// impl Error for SuperError {
48 ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
49 ///         Some(&self.source)
50 ///     }
51 /// }
52 ///
53 /// #[derive(Debug)]
54 /// struct SuperErrorSideKick;
55 ///
56 /// impl fmt::Display for SuperErrorSideKick {
57 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 ///         write!(f, "SuperErrorSideKick is here!")
59 ///     }
60 /// }
61 ///
62 /// impl Error for SuperErrorSideKick {}
63 ///
64 /// fn get_super_error() -> Result<(), SuperError> {
65 ///     Err(SuperError { source: SuperErrorSideKick })
66 /// }
67 ///
68 /// fn main() {
69 ///     match get_super_error() {
70 ///         Err(e) => println!("Error: {}", Report::new(e)),
71 ///         _ => println!("No error"),
72 ///     }
73 /// }
74 /// ```
75 ///
76 /// This example produces the following output:
77 ///
78 /// ```console
79 /// Error: SuperError is here!: SuperErrorSideKick is here!
80 /// ```
81 ///
82 /// ## Output consistency
83 ///
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`:
86 ///
87 /// ```should_panic
88 /// #![feature(error_reporter)]
89 /// use std::error::Report;
90 /// # use std::error::Error;
91 /// # use std::fmt;
92 /// # #[derive(Debug)]
93 /// # struct SuperError {
94 /// #     source: SuperErrorSideKick,
95 /// # }
96 /// # impl fmt::Display for SuperError {
97 /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 /// #         write!(f, "SuperError is here!")
99 /// #     }
100 /// # }
101 /// # impl Error for SuperError {
102 /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
103 /// #         Some(&self.source)
104 /// #     }
105 /// # }
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!")
111 /// #     }
112 /// # }
113 /// # impl Error for SuperErrorSideKick {}
114 /// # fn get_super_error() -> Result<(), SuperError> {
115 /// #     Err(SuperError { source: SuperErrorSideKick })
116 /// # }
117 ///
118 /// get_super_error().map_err(Report::new).unwrap();
119 /// ```
120 ///
121 /// This example produces the following output:
122 ///
123 /// ```console
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
126 /// ```
127 ///
128 /// ## Return from `main`
129 ///
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
132 /// from `main`.
133 ///
134 /// ```should_panic
135 /// #![feature(error_reporter)]
136 /// use std::error::Report;
137 /// # use std::error::Error;
138 /// # use std::fmt;
139 /// # #[derive(Debug)]
140 /// # struct SuperError {
141 /// #     source: SuperErrorSideKick,
142 /// # }
143 /// # impl fmt::Display for SuperError {
144 /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 /// #         write!(f, "SuperError is here!")
146 /// #     }
147 /// # }
148 /// # impl Error for SuperError {
149 /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
150 /// #         Some(&self.source)
151 /// #     }
152 /// # }
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!")
158 /// #     }
159 /// # }
160 /// # impl Error for SuperErrorSideKick {}
161 /// # fn get_super_error() -> Result<(), SuperError> {
162 /// #     Err(SuperError { source: SuperErrorSideKick })
163 /// # }
164 ///
165 /// fn main() -> Result<(), Report<SuperError>> {
166 ///     get_super_error()?;
167 ///     Ok(())
168 /// }
169 /// ```
170 ///
171 /// This example produces the following output:
172 ///
173 /// ```console
174 /// Error: SuperError is here!: SuperErrorSideKick is here!
175 /// ```
176 ///
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.
180 ///
181 /// ```should_panic
182 /// #![feature(error_reporter)]
183 /// use std::error::Report;
184 /// # use std::error::Error;
185 /// # use std::fmt;
186 /// # #[derive(Debug)]
187 /// # struct SuperError {
188 /// #     source: SuperErrorSideKick,
189 /// # }
190 /// # impl fmt::Display for SuperError {
191 /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 /// #         write!(f, "SuperError is here!")
193 /// #     }
194 /// # }
195 /// # impl Error for SuperError {
196 /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
197 /// #         Some(&self.source)
198 /// #     }
199 /// # }
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!")
205 /// #     }
206 /// # }
207 /// # impl Error for SuperErrorSideKick {}
208 /// # fn get_super_error() -> Result<(), SuperError> {
209 /// #     Err(SuperError { source: SuperErrorSideKick })
210 /// # }
211 ///
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))?;
216 ///     Ok(())
217 /// }
218 /// ```
219 ///
220 /// This example produces the following output:
221 ///
222 /// ```console
223 /// Error: SuperError is here!
224 ///
225 /// Caused by:
226 ///       SuperErrorSideKick is here!
227 /// ```
228 #[unstable(feature = "error_reporter", issue = "90172")]
229 pub struct Report<E = Box<dyn Error>> {
230     /// The error being reported.
231     error: E,
232     /// Whether a backtrace should be included as part of the report.
233     show_backtrace: bool,
234     /// Whether the report should be pretty-printed.
235     pretty: bool,
236 }
237
238 impl<E> Report<E>
239 where
240     Report<E>: From<E>,
241 {
242     /// Create a new `Report` from an input error.
243     #[unstable(feature = "error_reporter", issue = "90172")]
244     pub fn new(error: E) -> Report<E> {
245         Self::from(error)
246     }
247 }
248
249 impl<E> Report<E> {
250     /// Enable pretty-printing the report across multiple lines.
251     ///
252     /// # Examples
253     ///
254     /// ```rust
255     /// #![feature(error_reporter)]
256     /// use std::error::Report;
257     /// # use std::error::Error;
258     /// # use std::fmt;
259     /// # #[derive(Debug)]
260     /// # struct SuperError {
261     /// #     source: SuperErrorSideKick,
262     /// # }
263     /// # impl fmt::Display for SuperError {
264     /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265     /// #         write!(f, "SuperError is here!")
266     /// #     }
267     /// # }
268     /// # impl Error for SuperError {
269     /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
270     /// #         Some(&self.source)
271     /// #     }
272     /// # }
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!")
278     /// #     }
279     /// # }
280     /// # impl Error for SuperErrorSideKick {}
281     ///
282     /// let error = SuperError { source: SuperErrorSideKick };
283     /// let report = Report::new(error).pretty(true);
284     /// eprintln!("Error: {report:?}");
285     /// ```
286     ///
287     /// This example produces the following output:
288     ///
289     /// ```console
290     /// Error: SuperError is here!
291     ///
292     /// Caused by:
293     ///       SuperErrorSideKick is here!
294     /// ```
295     ///
296     /// When there are multiple source errors the causes will be numbered in order of iteration
297     /// starting from the outermost error.
298     ///
299     /// ```rust
300     /// #![feature(error_reporter)]
301     /// use std::error::Report;
302     /// # use std::error::Error;
303     /// # use std::fmt;
304     /// # #[derive(Debug)]
305     /// # struct SuperError {
306     /// #     source: SuperErrorSideKick,
307     /// # }
308     /// # impl fmt::Display for SuperError {
309     /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310     /// #         write!(f, "SuperError is here!")
311     /// #     }
312     /// # }
313     /// # impl Error for SuperError {
314     /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
315     /// #         Some(&self.source)
316     /// #     }
317     /// # }
318     /// # #[derive(Debug)]
319     /// # struct SuperErrorSideKick {
320     /// #     source: SuperErrorSideKickSideKick,
321     /// # }
322     /// # impl fmt::Display for SuperErrorSideKick {
323     /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
324     /// #         write!(f, "SuperErrorSideKick is here!")
325     /// #     }
326     /// # }
327     /// # impl Error for SuperErrorSideKick {
328     /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
329     /// #         Some(&self.source)
330     /// #     }
331     /// # }
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!")
337     /// #     }
338     /// # }
339     /// # impl Error for SuperErrorSideKickSideKick { }
340     ///
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:?}");
346     /// ```
347     ///
348     /// This example produces the following output:
349     ///
350     /// ```console
351     /// Error: SuperError is here!
352     ///
353     /// Caused by:
354     ///    0: SuperErrorSideKick is here!
355     ///    1: SuperErrorSideKickSideKick is here!
356     /// ```
357     #[unstable(feature = "error_reporter", issue = "90172")]
358     pub fn pretty(mut self, pretty: bool) -> Self {
359         self.pretty = pretty;
360         self
361     }
362
363     /// Display backtrace if available when using pretty output format.
364     ///
365     /// # Examples
366     ///
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`.
370     ///
371     /// ```rust
372     /// #![feature(error_reporter)]
373     /// #![feature(provide_any)]
374     /// #![feature(error_generic_member_access)]
375     /// # use std::error::Error;
376     /// # use std::fmt;
377     /// use std::any::Demand;
378     /// use std::error::Report;
379     /// use std::backtrace::Backtrace;
380     ///
381     /// # #[derive(Debug)]
382     /// # struct SuperError {
383     /// #     source: SuperErrorSideKick,
384     /// # }
385     /// # impl fmt::Display for SuperError {
386     /// #     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387     /// #         write!(f, "SuperError is here!")
388     /// #     }
389     /// # }
390     /// # impl Error for SuperError {
391     /// #     fn source(&self) -> Option<&(dyn Error + 'static)> {
392     /// #         Some(&self.source)
393     /// #     }
394     /// # }
395     /// #[derive(Debug)]
396     /// struct SuperErrorSideKick {
397     ///     backtrace: Backtrace,
398     /// }
399     ///
400     /// impl SuperErrorSideKick {
401     ///     fn new() -> SuperErrorSideKick {
402     ///         SuperErrorSideKick { backtrace: Backtrace::force_capture() }
403     ///     }
404     /// }
405     ///
406     /// impl Error for SuperErrorSideKick {
407     ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
408     ///         demand.provide_ref::<Backtrace>(&self.backtrace);
409     ///     }
410     /// }
411     ///
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!")
416     /// #     }
417     /// # }
418     ///
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:?}");
423     /// ```
424     ///
425     /// This example produces something similar to the following output:
426     ///
427     /// ```console
428     /// Error: SuperError is here!
429     ///
430     /// Caused by:
431     ///       SuperErrorSideKick is here!
432     ///
433     /// Stack backtrace:
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
443     ///    9: main
444     ///   10: __libc_start_main
445     ///   11: _start
446     /// ```
447     #[unstable(feature = "error_reporter", issue = "90172")]
448     pub fn show_backtrace(mut self, show_backtrace: bool) -> Self {
449         self.show_backtrace = show_backtrace;
450         self
451     }
452 }
453
454 impl<E> Report<E>
455 where
456     E: Error,
457 {
458     fn backtrace(&self) -> Option<&Backtrace> {
459         // have to grab the backtrace on the first error directly since that error may not be
460         // 'static
461         let backtrace = (&self.error as &dyn Error).request_ref();
462         let backtrace = backtrace.or_else(|| {
463             self.error
464                 .source()
465                 .map(|source| source.sources().find_map(|source| source.request_ref()))
466                 .flatten()
467         });
468         backtrace
469     }
470
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)?;
475
476         let sources = self.error.source().into_iter().flat_map(<dyn Error>::sources);
477
478         for cause in sources {
479             write!(f, ": {cause}")?;
480         }
481
482         Ok(())
483     }
484
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;
489
490         write!(f, "{error}")?;
491
492         if let Some(cause) = error.source() {
493             write!(f, "\n\nCaused by:")?;
494
495             let multiple = cause.source().is_some();
496
497             for (ind, error) in cause.sources().enumerate() {
498                 writeln!(f)?;
499                 let mut indented = Indented { inner: f };
500                 if multiple {
501                     write!(indented, "{ind: >4}: {error}")?;
502                 } else {
503                     write!(indented, "      {error}")?;
504                 }
505             }
506         }
507
508         if self.show_backtrace {
509             let backtrace = self.backtrace();
510
511             if let Some(backtrace) = backtrace {
512                 let backtrace = backtrace.to_string();
513
514                 f.write_str("\n\nStack backtrace:\n")?;
515                 f.write_str(backtrace.trim_end())?;
516             }
517         }
518
519         Ok(())
520     }
521 }
522
523 #[unstable(feature = "error_reporter", issue = "90172")]
524 impl<E> From<E> for Report<E>
525 where
526     E: Error,
527 {
528     fn from(error: E) -> Self {
529         Report { error, show_backtrace: false, pretty: false }
530     }
531 }
532
533 #[unstable(feature = "error_reporter", issue = "90172")]
534 impl<E> fmt::Display for Report<E>
535 where
536     E: Error,
537 {
538     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539         if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) }
540     }
541 }
542
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>
547 where
548     Report<E>: fmt::Display,
549 {
550     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551         fmt::Display::fmt(self, f)
552     }
553 }
554
555 /// Wrapper type for indenting the inner source.
556 struct Indented<'a, D> {
557     inner: &'a mut D,
558 }
559
560 impl<T> Write for Indented<'_, T>
561 where
562     T: Write,
563 {
564     fn write_str(&mut self, s: &str) -> fmt::Result {
565         for (i, line) in s.split('\n').enumerate() {
566             if i > 0 {
567                 self.inner.write_char('\n')?;
568                 self.inner.write_str("      ")?;
569             }
570
571             self.inner.write_str(line)?;
572         }
573
574         Ok(())
575     }
576 }