]> git.proxmox.com Git - rustc.git/blame - library/std/src/error.rs
New upstream version 1.59.0+dfsg1
[rustc.git] / library / std / src / error.rs
CommitLineData
c34b1796 1//! Traits for working with Errors.
c34b1796
AL
2
3#![stable(feature = "rust1", since = "1.0.0")]
4
5// A note about crates and the facade:
6//
7// Originally, the `Error` trait was defined in libcore, and the impls
8// were scattered about. However, coherence objected to this
9// arrangement, because to create the blanket impls for `Box` required
10// knowing that `&str: !Error`, and we have no means to deal with that
11// sort of conflict just now. Therefore, for the time being, we have
12// moved the `Error` trait into libstd. As we evolve a sol'n to the
13// coherence challenge (e.g., specialization, neg impls, etc) we can
14// reconsider what crate these items belong in.
15
1b1a35ee
XL
16#[cfg(test)]
17mod tests;
18
abe05a73 19use core::array;
f9f354fc 20use core::convert::Infallible;
532ac7d7 21
fc512014 22use crate::alloc::{AllocError, LayoutError};
532ac7d7 23use crate::any::TypeId;
e1599b0c 24use crate::backtrace::Backtrace;
532ac7d7
XL
25use crate::borrow::Cow;
26use crate::cell;
27use crate::char;
28use crate::fmt::{self, Debug, Display};
29use crate::mem::transmute;
30use crate::num;
31use crate::str;
32use crate::string;
6a06907d 33use crate::sync::Arc;
c295e0f8 34use crate::time;
c34b1796 35
83c7162d 36/// `Error` is a trait representing the basic expectations for error values,
cdc7bbd5 37/// i.e., values of type `E` in [`Result<T, E>`].
83c7162d 38///
cdc7bbd5
XL
39/// Errors must describe themselves through the [`Display`] and [`Debug`]
40/// traits. Error messages are typically concise lowercase sentences without
41/// trailing punctuation:
42///
43/// ```
44/// let err = "NaN".parse::<u32>().unwrap_err();
45/// assert_eq!(err.to_string(), "invalid digit found in string");
46/// ```
47///
48/// Errors may provide cause chain information. [`Error::source()`] is generally
49/// used when errors cross "abstraction boundaries". If one module must report
50/// an error that is caused by an error from a lower-level module, it can allow
51/// accessing that error via [`Error::source()`]. This makes it possible for the
52/// high-level module to provide its own errors while also revealing some of the
1b1a35ee 53/// implementation for debugging via `source` chains.
c34b1796 54#[stable(feature = "rust1", since = "1.0.0")]
9e0c209e 55pub trait Error: Debug + Display {
b7449926
XL
56 /// The lower-level source of this error, if any.
57 ///
58 /// # Examples
59 ///
60 /// ```
61 /// use std::error::Error;
62 /// use std::fmt;
63 ///
64 /// #[derive(Debug)]
65 /// struct SuperError {
66 /// side: SuperErrorSideKick,
67 /// }
68 ///
69 /// impl fmt::Display for SuperError {
532ac7d7 70 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
b7449926
XL
71 /// write!(f, "SuperError is here!")
72 /// }
73 /// }
74 ///
75 /// impl Error for SuperError {
b7449926
XL
76 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
77 /// Some(&self.side)
78 /// }
79 /// }
80 ///
81 /// #[derive(Debug)]
82 /// struct SuperErrorSideKick;
83 ///
84 /// impl fmt::Display for SuperErrorSideKick {
532ac7d7 85 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
b7449926
XL
86 /// write!(f, "SuperErrorSideKick is here!")
87 /// }
88 /// }
89 ///
dfeec247 90 /// impl Error for SuperErrorSideKick {}
b7449926
XL
91 ///
92 /// fn get_super_error() -> Result<(), SuperError> {
93 /// Err(SuperError { side: SuperErrorSideKick })
94 /// }
95 ///
96 /// fn main() {
97 /// match get_super_error() {
98 /// Err(e) => {
ba9703b0 99 /// println!("Error: {}", e);
b7449926
XL
100 /// println!("Caused by: {}", e.source().unwrap());
101 /// }
102 /// _ => println!("No error"),
103 /// }
104 /// }
105 /// ```
106 #[stable(feature = "error_source", since = "1.30.0")]
dfeec247
XL
107 fn source(&self) -> Option<&(dyn Error + 'static)> {
108 None
109 }
bd371182 110
e1599b0c 111 /// Gets the `TypeId` of `self`.
bd371182 112 #[doc(hidden)]
dfeec247
XL
113 #[unstable(
114 feature = "error_type_id",
115 reason = "this is memory-unsafe to override in user code",
116 issue = "60784"
117 )]
118 fn type_id(&self, _: private::Internal) -> TypeId
119 where
120 Self: 'static,
121 {
bd371182
AL
122 TypeId::of::<Self>()
123 }
e1599b0c 124
60c5eb7d 125 /// Returns a stack backtrace, if available, of where this error occurred.
e1599b0c
XL
126 ///
127 /// This function allows inspecting the location, in code, of where an error
128 /// happened. The returned `Backtrace` contains information about the stack
129 /// trace of the OS thread of execution of where the error originated from.
130 ///
131 /// Note that not all errors contain a `Backtrace`. Also note that a
132 /// `Backtrace` may actually be empty. For more information consult the
133 /// `Backtrace` type itself.
134 #[unstable(feature = "backtrace", issue = "53487")]
135 fn backtrace(&self) -> Option<&Backtrace> {
136 None
137 }
dfeec247
XL
138
139 /// ```
140 /// if let Err(e) = "xc".parse::<u32>() {
141 /// // Print `e` itself, no need for description().
142 /// eprintln!("Error: {}", e);
143 /// }
144 /// ```
145 #[stable(feature = "rust1", since = "1.0.0")]
146 #[rustc_deprecated(since = "1.42.0", reason = "use the Display impl or to_string()")]
147 fn description(&self) -> &str {
148 "description() is deprecated; use Display"
149 }
150
151 #[stable(feature = "rust1", since = "1.0.0")]
152 #[rustc_deprecated(
153 since = "1.33.0",
154 reason = "replaced by Error::source, which can support downcasting"
155 )]
156 #[allow(missing_docs)]
157 fn cause(&self) -> Option<&dyn Error> {
158 self.source()
159 }
c34b1796
AL
160}
161
48663c56
XL
162mod private {
163 // This is a hack to prevent `type_id` from being overridden by `Error`
164 // implementations, since that can enable unsound downcasting.
165 #[unstable(feature = "error_type_id", issue = "60784")]
166 #[derive(Debug)]
167 pub struct Internal;
168}
169
c34b1796 170#[stable(feature = "rust1", since = "1.0.0")]
8faf50e0 171impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
0bf4aa26
XL
172 /// Converts a type of [`Error`] into a box of dyn [`Error`].
173 ///
174 /// # Examples
175 ///
176 /// ```
177 /// use std::error::Error;
178 /// use std::fmt;
179 /// use std::mem;
180 ///
181 /// #[derive(Debug)]
182 /// struct AnError;
183 ///
184 /// impl fmt::Display for AnError {
532ac7d7 185 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
c295e0f8 186 /// write!(f, "An error")
0bf4aa26
XL
187 /// }
188 /// }
189 ///
dfeec247 190 /// impl Error for AnError {}
0bf4aa26
XL
191 ///
192 /// let an_error = AnError;
193 /// assert!(0 == mem::size_of_val(&an_error));
dc9dc135 194 /// let a_boxed_error = Box::<dyn Error>::from(an_error);
0bf4aa26
XL
195 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
196 /// ```
8faf50e0 197 fn from(err: E) -> Box<dyn Error + 'a> {
c34b1796
AL
198 Box::new(err)
199 }
200}
201
202#[stable(feature = "rust1", since = "1.0.0")]
8faf50e0 203impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
e74abb32
XL
204 /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
205 /// dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26
XL
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use std::error::Error;
211 /// use std::fmt;
212 /// use std::mem;
213 ///
214 /// #[derive(Debug)]
215 /// struct AnError;
216 ///
217 /// impl fmt::Display for AnError {
532ac7d7 218 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
c295e0f8 219 /// write!(f, "An error")
0bf4aa26
XL
220 /// }
221 /// }
222 ///
dfeec247 223 /// impl Error for AnError {}
0bf4aa26
XL
224 ///
225 /// unsafe impl Send for AnError {}
226 ///
227 /// unsafe impl Sync for AnError {}
228 ///
229 /// let an_error = AnError;
230 /// assert!(0 == mem::size_of_val(&an_error));
dc9dc135 231 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
0bf4aa26
XL
232 /// assert!(
233 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
234 /// ```
8faf50e0 235 fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
c34b1796
AL
236 Box::new(err)
237 }
238}
239
240#[stable(feature = "rust1", since = "1.0.0")]
8faf50e0 241impl From<String> for Box<dyn Error + Send + Sync> {
e74abb32 242 /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26
XL
243 ///
244 /// # Examples
245 ///
246 /// ```
247 /// use std::error::Error;
248 /// use std::mem;
249 ///
250 /// let a_string_error = "a string error".to_string();
dc9dc135 251 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
0bf4aa26
XL
252 /// assert!(
253 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
254 /// ```
dfeec247 255 #[inline]
8faf50e0 256 fn from(err: String) -> Box<dyn Error + Send + Sync> {
c34b1796
AL
257 struct StringError(String);
258
259 impl Error for StringError {
dfeec247
XL
260 #[allow(deprecated)]
261 fn description(&self) -> &str {
262 &self.0
263 }
c34b1796
AL
264 }
265
266 impl Display for StringError {
532ac7d7 267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
c34b1796
AL
268 Display::fmt(&self.0, f)
269 }
270 }
271
dc9dc135
XL
272 // Purposefully skip printing "StringError(..)"
273 impl Debug for StringError {
274 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
275 Debug::fmt(&self.0, f)
276 }
277 }
278
9346a6ac
AL
279 Box::new(StringError(err))
280 }
281}
282
7cac9316 283#[stable(feature = "string_box_error", since = "1.6.0")]
8faf50e0 284impl From<String> for Box<dyn Error> {
0bf4aa26
XL
285 /// Converts a [`String`] into a box of dyn [`Error`].
286 ///
287 /// # Examples
288 ///
289 /// ```
290 /// use std::error::Error;
291 /// use std::mem;
292 ///
293 /// let a_string_error = "a string error".to_string();
dc9dc135 294 /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
0bf4aa26
XL
295 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
296 /// ```
8faf50e0
XL
297 fn from(str_err: String) -> Box<dyn Error> {
298 let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
299 let err2: Box<dyn Error> = err1;
92a42be0
SL
300 err2
301 }
302}
303
9346a6ac 304#[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 305impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
e74abb32 306 /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26 307 ///
3dfed10e 308 /// [`str`]: prim@str
48663c56 309 ///
0bf4aa26
XL
310 /// # Examples
311 ///
312 /// ```
313 /// use std::error::Error;
314 /// use std::mem;
315 ///
316 /// let a_str_error = "a str error";
dc9dc135 317 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
0bf4aa26
XL
318 /// assert!(
319 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
320 /// ```
dfeec247 321 #[inline]
532ac7d7 322 fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
62682a34 323 From::from(String::from(err))
c34b1796
AL
324 }
325}
326
7cac9316 327#[stable(feature = "string_box_error", since = "1.6.0")]
532ac7d7 328impl From<&str> for Box<dyn Error> {
0bf4aa26
XL
329 /// Converts a [`str`] into a box of dyn [`Error`].
330 ///
3dfed10e 331 /// [`str`]: prim@str
48663c56 332 ///
0bf4aa26
XL
333 /// # Examples
334 ///
335 /// ```
336 /// use std::error::Error;
337 /// use std::mem;
338 ///
339 /// let a_str_error = "a str error";
dc9dc135 340 /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
0bf4aa26
XL
341 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
342 /// ```
532ac7d7 343 fn from(err: &str) -> Box<dyn Error> {
92a42be0
SL
344 From::from(String::from(err))
345 }
346}
347
ea8adc8c 348#[stable(feature = "cow_box_error", since = "1.22.0")]
8faf50e0 349impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
e74abb32 350 /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26
XL
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// use std::error::Error;
356 /// use std::mem;
357 /// use std::borrow::Cow;
358 ///
359 /// let a_cow_str_error = Cow::from("a str error");
dc9dc135 360 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
0bf4aa26
XL
361 /// assert!(
362 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
363 /// ```
8faf50e0 364 fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
ea8adc8c
XL
365 From::from(String::from(err))
366 }
367}
368
369#[stable(feature = "cow_box_error", since = "1.22.0")]
8faf50e0 370impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
0bf4aa26
XL
371 /// Converts a [`Cow`] into a box of dyn [`Error`].
372 ///
373 /// # Examples
374 ///
375 /// ```
376 /// use std::error::Error;
377 /// use std::mem;
378 /// use std::borrow::Cow;
379 ///
380 /// let a_cow_str_error = Cow::from("a str error");
dc9dc135 381 /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
0bf4aa26
XL
382 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
383 /// ```
8faf50e0 384 fn from(err: Cow<'a, str>) -> Box<dyn Error> {
ea8adc8c
XL
385 From::from(String::from(err))
386 }
387}
388
ff7c6d11 389#[unstable(feature = "never_type", issue = "35121")]
dfeec247
XL
390impl Error for ! {}
391
392#[unstable(
393 feature = "allocator_api",
394 reason = "the precise API and guarantees it provides may be tweaked.",
395 issue = "32838"
396)]
1b1a35ee 397impl Error for AllocError {}
dfeec247 398
1b1a35ee 399#[stable(feature = "alloc_layout", since = "1.28.0")]
fc512014 400impl Error for LayoutError {}
dfeec247 401
c34b1796
AL
402#[stable(feature = "rust1", since = "1.0.0")]
403impl Error for str::ParseBoolError {
dfeec247
XL
404 #[allow(deprecated)]
405 fn description(&self) -> &str {
406 "failed to parse bool"
407 }
c34b1796
AL
408}
409
410#[stable(feature = "rust1", since = "1.0.0")]
411impl Error for str::Utf8Error {
dfeec247 412 #[allow(deprecated)]
c34b1796 413 fn description(&self) -> &str {
9346a6ac 414 "invalid utf-8: corrupt contents"
c34b1796
AL
415 }
416}
417
418#[stable(feature = "rust1", since = "1.0.0")]
419impl Error for num::ParseIntError {
dfeec247 420 #[allow(deprecated)]
c34b1796 421 fn description(&self) -> &str {
62682a34 422 self.__description()
c34b1796
AL
423 }
424}
425
9fa01778 426#[stable(feature = "try_from", since = "1.34.0")]
a7813a04 427impl Error for num::TryFromIntError {
dfeec247 428 #[allow(deprecated)]
a7813a04
XL
429 fn description(&self) -> &str {
430 self.__description()
431 }
432}
433
9fa01778 434#[stable(feature = "try_from", since = "1.34.0")]
abe05a73 435impl Error for array::TryFromSliceError {
dfeec247 436 #[allow(deprecated)]
abe05a73
XL
437 fn description(&self) -> &str {
438 self.__description()
439 }
440}
441
c34b1796
AL
442#[stable(feature = "rust1", since = "1.0.0")]
443impl Error for num::ParseFloatError {
dfeec247 444 #[allow(deprecated)]
c34b1796 445 fn description(&self) -> &str {
d9579d0f 446 self.__description()
c34b1796
AL
447 }
448}
449
450#[stable(feature = "rust1", since = "1.0.0")]
451impl Error for string::FromUtf8Error {
dfeec247 452 #[allow(deprecated)]
c34b1796
AL
453 fn description(&self) -> &str {
454 "invalid utf-8"
455 }
456}
457
458#[stable(feature = "rust1", since = "1.0.0")]
459impl Error for string::FromUtf16Error {
dfeec247 460 #[allow(deprecated)]
c34b1796
AL
461 fn description(&self) -> &str {
462 "invalid utf-16"
463 }
464}
465
7453a54e 466#[stable(feature = "str_parse_error2", since = "1.8.0")]
f9f354fc 467impl Error for Infallible {
7453a54e
SL
468 fn description(&self) -> &str {
469 match *self {}
470 }
471}
472
54a0048b
SL
473#[stable(feature = "decode_utf16", since = "1.9.0")]
474impl Error for char::DecodeUtf16Error {
dfeec247 475 #[allow(deprecated)]
54a0048b
SL
476 fn description(&self) -> &str {
477 "unpaired surrogate found"
478 }
479}
480
a2a8927a
XL
481#[stable(feature = "u8_from_char", since = "1.59.0")]
482impl Error for char::TryFromCharError {}
483
6a06907d
XL
484#[unstable(feature = "map_try_insert", issue = "82766")]
485impl<'a, K: Debug + Ord, V: Debug> Error
486 for crate::collections::btree_map::OccupiedError<'a, K, V>
487{
488 #[allow(deprecated)]
489 fn description(&self) -> &str {
490 "key already exists"
491 }
492}
493
494#[unstable(feature = "map_try_insert", issue = "82766")]
495impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> {
496 #[allow(deprecated)]
497 fn description(&self) -> &str {
498 "key already exists"
499 }
500}
501
7cac9316 502#[stable(feature = "box_error", since = "1.8.0")]
7453a54e 503impl<T: Error> Error for Box<T> {
dfeec247 504 #[allow(deprecated, deprecated_in_future)]
7453a54e
SL
505 fn description(&self) -> &str {
506 Error::description(&**self)
507 }
508
0731742a 509 #[allow(deprecated)]
8faf50e0 510 fn cause(&self) -> Option<&dyn Error> {
7453a54e
SL
511 Error::cause(&**self)
512 }
dc9dc135
XL
513
514 fn source(&self) -> Option<&(dyn Error + 'static)> {
515 Error::source(&**self)
516 }
7453a54e
SL
517}
518
5869c6ff
XL
519#[stable(feature = "error_by_ref", since = "1.51.0")]
520impl<'a, T: Error + ?Sized> Error for &'a T {
521 #[allow(deprecated, deprecated_in_future)]
522 fn description(&self) -> &str {
523 Error::description(&**self)
524 }
525
526 #[allow(deprecated)]
527 fn cause(&self) -> Option<&dyn Error> {
528 Error::cause(&**self)
529 }
530
531 fn source(&self) -> Option<&(dyn Error + 'static)> {
532 Error::source(&**self)
533 }
534
535 fn backtrace(&self) -> Option<&Backtrace> {
536 Error::backtrace(&**self)
537 }
538}
539
6a06907d
XL
540#[stable(feature = "arc_error", since = "1.52.0")]
541impl<T: Error + ?Sized> Error for Arc<T> {
542 #[allow(deprecated, deprecated_in_future)]
543 fn description(&self) -> &str {
544 Error::description(&**self)
545 }
546
547 #[allow(deprecated)]
548 fn cause(&self) -> Option<&dyn Error> {
549 Error::cause(&**self)
550 }
551
552 fn source(&self) -> Option<&(dyn Error + 'static)> {
553 Error::source(&**self)
554 }
555
556 fn backtrace(&self) -> Option<&Backtrace> {
557 Error::backtrace(&**self)
558 }
559}
560
3157f602
XL
561#[stable(feature = "fmt_error", since = "1.11.0")]
562impl Error for fmt::Error {
dfeec247 563 #[allow(deprecated)]
3157f602
XL
564 fn description(&self) -> &str {
565 "an error occurred when formatting an argument"
566 }
567}
568
9e0c209e
SL
569#[stable(feature = "try_borrow", since = "1.13.0")]
570impl Error for cell::BorrowError {
dfeec247 571 #[allow(deprecated)]
5bcae85e
SL
572 fn description(&self) -> &str {
573 "already mutably borrowed"
574 }
575}
576
9e0c209e
SL
577#[stable(feature = "try_borrow", since = "1.13.0")]
578impl Error for cell::BorrowMutError {
dfeec247 579 #[allow(deprecated)]
5bcae85e
SL
580 fn description(&self) -> &str {
581 "already borrowed"
582 }
583}
584
9fa01778 585#[stable(feature = "try_from", since = "1.34.0")]
9e0c209e 586impl Error for char::CharTryFromError {
dfeec247 587 #[allow(deprecated)]
9e0c209e
SL
588 fn description(&self) -> &str {
589 "converted integer out of range for `char`"
590 }
591}
592
041b39d2
XL
593#[stable(feature = "char_from_str", since = "1.20.0")]
594impl Error for char::ParseCharError {
dfeec247 595 #[allow(deprecated)]
041b39d2
XL
596 fn description(&self) -> &str {
597 self.__description()
598 }
599}
600
c295e0f8 601#[stable(feature = "try_reserve", since = "1.57.0")]
ba9703b0
XL
602impl Error for alloc::collections::TryReserveError {}
603
136023e0 604#[unstable(feature = "duration_checked_float", issue = "83400")]
c295e0f8 605impl Error for time::FromSecsError {}
136023e0 606
e1599b0c 607// Copied from `any.rs`.
8faf50e0 608impl dyn Error + 'static {
9fa01778 609 /// Returns `true` if the boxed type is the same as `T`
c1a9b12d 610 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
611 #[inline]
612 pub fn is<T: Error + 'static>(&self) -> bool {
e1599b0c 613 // Get `TypeId` of the type this function is instantiated with.
bd371182
AL
614 let t = TypeId::of::<T>();
615
e1599b0c 616 // Get `TypeId` of the type in the trait object.
48663c56 617 let boxed = self.type_id(private::Internal);
bd371182 618
e1599b0c 619 // Compare both `TypeId`s on equality.
bd371182
AL
620 t == boxed
621 }
622
623 /// Returns some reference to the boxed value if it is of type `T`, or
624 /// `None` if it isn't.
c1a9b12d 625 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
626 #[inline]
627 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
628 if self.is::<T>() {
dfeec247 629 unsafe { Some(&*(self as *const dyn Error as *const T)) }
bd371182
AL
630 } else {
631 None
632 }
633 }
634
635 /// Returns some mutable reference to the boxed value if it is of type `T`, or
636 /// `None` if it isn't.
c1a9b12d 637 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
638 #[inline]
639 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
640 if self.is::<T>() {
dfeec247 641 unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) }
bd371182
AL
642 } else {
643 None
644 }
645 }
646}
647
8faf50e0 648impl dyn Error + 'static + Send {
e1599b0c 649 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d 650 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
651 #[inline]
652 pub fn is<T: Error + 'static>(&self) -> bool {
8faf50e0 653 <dyn Error + 'static>::is::<T>(self)
bd371182
AL
654 }
655
e1599b0c 656 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d 657 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
658 #[inline]
659 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
8faf50e0 660 <dyn Error + 'static>::downcast_ref::<T>(self)
bd371182
AL
661 }
662
e1599b0c 663 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d
SL
664 #[stable(feature = "error_downcast", since = "1.3.0")]
665 #[inline]
666 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
8faf50e0 667 <dyn Error + 'static>::downcast_mut::<T>(self)
c1a9b12d
SL
668 }
669}
670
8faf50e0 671impl dyn Error + 'static + Send + Sync {
e1599b0c 672 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d
SL
673 #[stable(feature = "error_downcast", since = "1.3.0")]
674 #[inline]
675 pub fn is<T: Error + 'static>(&self) -> bool {
8faf50e0 676 <dyn Error + 'static>::is::<T>(self)
c1a9b12d
SL
677 }
678
e1599b0c 679 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d
SL
680 #[stable(feature = "error_downcast", since = "1.3.0")]
681 #[inline]
682 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
8faf50e0 683 <dyn Error + 'static>::downcast_ref::<T>(self)
c1a9b12d
SL
684 }
685
e1599b0c 686 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d 687 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
688 #[inline]
689 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
8faf50e0 690 <dyn Error + 'static>::downcast_mut::<T>(self)
bd371182
AL
691 }
692}
693
8faf50e0 694impl dyn Error {
bd371182 695 #[inline]
c1a9b12d 696 #[stable(feature = "error_downcast", since = "1.3.0")]
e1599b0c 697 /// Attempts to downcast the box to a concrete type.
8faf50e0 698 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
bd371182
AL
699 if self.is::<T>() {
700 unsafe {
8faf50e0 701 let raw: *mut dyn Error = Box::into_raw(self);
9e0c209e 702 Ok(Box::from_raw(raw as *mut T))
bd371182
AL
703 }
704 } else {
705 Err(self)
706 }
707 }
9fa01778
XL
708
709 /// Returns an iterator starting with the current error and continuing with
1b1a35ee 710 /// recursively calling [`Error::source`].
9fa01778 711 ///
60c5eb7d
XL
712 /// If you want to omit the current error and only use its sources,
713 /// use `skip(1)`.
714 ///
9fa01778
XL
715 /// # Examples
716 ///
717 /// ```
718 /// #![feature(error_iter)]
719 /// use std::error::Error;
720 /// use std::fmt;
721 ///
722 /// #[derive(Debug)]
723 /// struct A;
724 ///
725 /// #[derive(Debug)]
726 /// struct B(Option<Box<dyn Error + 'static>>);
727 ///
728 /// impl fmt::Display for A {
532ac7d7 729 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9fa01778
XL
730 /// write!(f, "A")
731 /// }
732 /// }
733 ///
734 /// impl fmt::Display for B {
532ac7d7 735 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9fa01778
XL
736 /// write!(f, "B")
737 /// }
738 /// }
739 ///
740 /// impl Error for A {}
741 ///
742 /// impl Error for B {
743 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
744 /// self.0.as_ref().map(|e| e.as_ref())
745 /// }
746 /// }
747 ///
748 /// let b = B(Some(Box::new(A)));
749 ///
750 /// // let err : Box<Error> = b.into(); // or
751 /// let err = &b as &(dyn Error);
752 ///
60c5eb7d 753 /// let mut iter = err.chain();
9fa01778
XL
754 ///
755 /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
756 /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
757 /// assert!(iter.next().is_none());
758 /// assert!(iter.next().is_none());
759 /// ```
9fa01778
XL
760 #[unstable(feature = "error_iter", issue = "58520")]
761 #[inline]
60c5eb7d 762 pub fn chain(&self) -> Chain<'_> {
dfeec247 763 Chain { current: Some(self) }
9fa01778 764 }
9fa01778
XL
765}
766
60c5eb7d
XL
767/// An iterator over an [`Error`] and its sources.
768///
769/// If you want to omit the initial error and only process
770/// its sources, use `skip(1)`.
9fa01778 771#[unstable(feature = "error_iter", issue = "58520")]
60c5eb7d
XL
772#[derive(Clone, Debug)]
773pub struct Chain<'a> {
9fa01778
XL
774 current: Option<&'a (dyn Error + 'static)>,
775}
776
777#[unstable(feature = "error_iter", issue = "58520")]
60c5eb7d 778impl<'a> Iterator for Chain<'a> {
9fa01778
XL
779 type Item = &'a (dyn Error + 'static);
780
781 fn next(&mut self) -> Option<Self::Item> {
782 let current = self.current;
783 self.current = self.current.and_then(Error::source);
784 current
785 }
bd371182
AL
786}
787
8faf50e0 788impl dyn Error + Send {
bd371182 789 #[inline]
c1a9b12d 790 #[stable(feature = "error_downcast", since = "1.3.0")]
e1599b0c 791 /// Attempts to downcast the box to a concrete type.
dfeec247 792 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
8faf50e0
XL
793 let err: Box<dyn Error> = self;
794 <dyn Error>::downcast(err).map_err(|s| unsafe {
e1599b0c 795 // Reapply the `Send` marker.
8faf50e0 796 transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
bd371182
AL
797 })
798 }
799}
c1a9b12d 800
8faf50e0 801impl dyn Error + Send + Sync {
c1a9b12d
SL
802 #[inline]
803 #[stable(feature = "error_downcast", since = "1.3.0")]
e1599b0c 804 /// Attempts to downcast the box to a concrete type.
dfeec247 805 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
8faf50e0
XL
806 let err: Box<dyn Error> = self;
807 <dyn Error>::downcast(err).map_err(|s| unsafe {
e1599b0c 808 // Reapply the `Send + Sync` marker.
8faf50e0 809 transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
c1a9b12d
SL
810 })
811 }
812}