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