]> git.proxmox.com Git - rustc.git/blame - library/std/src/error.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[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;
c34b1796 34
83c7162d 35/// `Error` is a trait representing the basic expectations for error values,
0731742a 36/// i.e., values of type `E` in [`Result<T, E>`]. Errors must describe
83c7162d
XL
37/// themselves through the [`Display`] and [`Debug`] traits, and may provide
38/// cause chain information:
39///
1b1a35ee
XL
40/// [`Error::source()`] is generally used when errors cross
41/// "abstraction boundaries". If one module must report an error that is caused
42/// by an error from a lower-level module, it can allow accessing that error
43/// via [`Error::source()`]. This makes it possible for the high-level
44/// module to provide its own errors while also revealing some of the
45/// implementation for debugging via `source` chains.
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) => {
ba9703b0 91 /// println!("Error: {}", e);
b7449926
XL
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 ///
166 /// # Examples
167 ///
168 /// ```
169 /// use std::error::Error;
170 /// use std::fmt;
171 /// use std::mem;
172 ///
173 /// #[derive(Debug)]
174 /// struct AnError;
175 ///
176 /// impl fmt::Display for AnError {
532ac7d7 177 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
0bf4aa26
XL
178 /// write!(f , "An error")
179 /// }
180 /// }
181 ///
dfeec247 182 /// impl Error for AnError {}
0bf4aa26
XL
183 ///
184 /// let an_error = AnError;
185 /// assert!(0 == mem::size_of_val(&an_error));
dc9dc135 186 /// let a_boxed_error = Box::<dyn Error>::from(an_error);
0bf4aa26
XL
187 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
188 /// ```
8faf50e0 189 fn from(err: E) -> Box<dyn Error + 'a> {
c34b1796
AL
190 Box::new(err)
191 }
192}
193
194#[stable(feature = "rust1", since = "1.0.0")]
8faf50e0 195impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
e74abb32
XL
196 /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
197 /// dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26
XL
198 ///
199 /// # Examples
200 ///
201 /// ```
202 /// use std::error::Error;
203 /// use std::fmt;
204 /// use std::mem;
205 ///
206 /// #[derive(Debug)]
207 /// struct AnError;
208 ///
209 /// impl fmt::Display for AnError {
532ac7d7 210 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
0bf4aa26
XL
211 /// write!(f , "An error")
212 /// }
213 /// }
214 ///
dfeec247 215 /// impl Error for AnError {}
0bf4aa26
XL
216 ///
217 /// unsafe impl Send for AnError {}
218 ///
219 /// unsafe impl Sync for AnError {}
220 ///
221 /// let an_error = AnError;
222 /// assert!(0 == mem::size_of_val(&an_error));
dc9dc135 223 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
0bf4aa26
XL
224 /// assert!(
225 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
226 /// ```
8faf50e0 227 fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
c34b1796
AL
228 Box::new(err)
229 }
230}
231
232#[stable(feature = "rust1", since = "1.0.0")]
8faf50e0 233impl From<String> for Box<dyn Error + Send + Sync> {
e74abb32 234 /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26
XL
235 ///
236 /// # Examples
237 ///
238 /// ```
239 /// use std::error::Error;
240 /// use std::mem;
241 ///
242 /// let a_string_error = "a string error".to_string();
dc9dc135 243 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
0bf4aa26
XL
244 /// assert!(
245 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
246 /// ```
dfeec247 247 #[inline]
8faf50e0 248 fn from(err: String) -> Box<dyn Error + Send + Sync> {
c34b1796
AL
249 struct StringError(String);
250
251 impl Error for StringError {
dfeec247
XL
252 #[allow(deprecated)]
253 fn description(&self) -> &str {
254 &self.0
255 }
c34b1796
AL
256 }
257
258 impl Display for StringError {
532ac7d7 259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
c34b1796
AL
260 Display::fmt(&self.0, f)
261 }
262 }
263
dc9dc135
XL
264 // Purposefully skip printing "StringError(..)"
265 impl Debug for StringError {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 Debug::fmt(&self.0, f)
268 }
269 }
270
9346a6ac
AL
271 Box::new(StringError(err))
272 }
273}
274
7cac9316 275#[stable(feature = "string_box_error", since = "1.6.0")]
8faf50e0 276impl From<String> for Box<dyn Error> {
0bf4aa26
XL
277 /// Converts a [`String`] into a box of dyn [`Error`].
278 ///
279 /// # Examples
280 ///
281 /// ```
282 /// use std::error::Error;
283 /// use std::mem;
284 ///
285 /// let a_string_error = "a string error".to_string();
dc9dc135 286 /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
0bf4aa26
XL
287 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
288 /// ```
8faf50e0
XL
289 fn from(str_err: String) -> Box<dyn Error> {
290 let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
291 let err2: Box<dyn Error> = err1;
92a42be0
SL
292 err2
293 }
294}
295
9346a6ac 296#[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 297impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
e74abb32 298 /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26 299 ///
3dfed10e 300 /// [`str`]: prim@str
48663c56 301 ///
0bf4aa26
XL
302 /// # Examples
303 ///
304 /// ```
305 /// use std::error::Error;
306 /// use std::mem;
307 ///
308 /// let a_str_error = "a str error";
dc9dc135 309 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
0bf4aa26
XL
310 /// assert!(
311 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
312 /// ```
dfeec247 313 #[inline]
532ac7d7 314 fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
62682a34 315 From::from(String::from(err))
c34b1796
AL
316 }
317}
318
7cac9316 319#[stable(feature = "string_box_error", since = "1.6.0")]
532ac7d7 320impl From<&str> for Box<dyn Error> {
0bf4aa26
XL
321 /// Converts a [`str`] into a box of dyn [`Error`].
322 ///
3dfed10e 323 /// [`str`]: prim@str
48663c56 324 ///
0bf4aa26
XL
325 /// # Examples
326 ///
327 /// ```
328 /// use std::error::Error;
329 /// use std::mem;
330 ///
331 /// let a_str_error = "a str error";
dc9dc135 332 /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
0bf4aa26
XL
333 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
334 /// ```
532ac7d7 335 fn from(err: &str) -> Box<dyn Error> {
92a42be0
SL
336 From::from(String::from(err))
337 }
338}
339
ea8adc8c 340#[stable(feature = "cow_box_error", since = "1.22.0")]
8faf50e0 341impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
e74abb32 342 /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
0bf4aa26
XL
343 ///
344 /// # Examples
345 ///
346 /// ```
347 /// use std::error::Error;
348 /// use std::mem;
349 /// use std::borrow::Cow;
350 ///
351 /// let a_cow_str_error = Cow::from("a str error");
dc9dc135 352 /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
0bf4aa26
XL
353 /// assert!(
354 /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
355 /// ```
8faf50e0 356 fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
ea8adc8c
XL
357 From::from(String::from(err))
358 }
359}
360
361#[stable(feature = "cow_box_error", since = "1.22.0")]
8faf50e0 362impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
0bf4aa26
XL
363 /// Converts a [`Cow`] into a box of dyn [`Error`].
364 ///
365 /// # Examples
366 ///
367 /// ```
368 /// use std::error::Error;
369 /// use std::mem;
370 /// use std::borrow::Cow;
371 ///
372 /// let a_cow_str_error = Cow::from("a str error");
dc9dc135 373 /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
0bf4aa26
XL
374 /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
375 /// ```
8faf50e0 376 fn from(err: Cow<'a, str>) -> Box<dyn Error> {
ea8adc8c
XL
377 From::from(String::from(err))
378 }
379}
380
ff7c6d11 381#[unstable(feature = "never_type", issue = "35121")]
dfeec247
XL
382impl Error for ! {}
383
384#[unstable(
385 feature = "allocator_api",
386 reason = "the precise API and guarantees it provides may be tweaked.",
387 issue = "32838"
388)]
1b1a35ee 389impl Error for AllocError {}
dfeec247 390
1b1a35ee 391#[stable(feature = "alloc_layout", since = "1.28.0")]
fc512014 392impl Error for LayoutError {}
dfeec247 393
c34b1796
AL
394#[stable(feature = "rust1", since = "1.0.0")]
395impl Error for str::ParseBoolError {
dfeec247
XL
396 #[allow(deprecated)]
397 fn description(&self) -> &str {
398 "failed to parse bool"
399 }
c34b1796
AL
400}
401
402#[stable(feature = "rust1", since = "1.0.0")]
403impl Error for str::Utf8Error {
dfeec247 404 #[allow(deprecated)]
c34b1796 405 fn description(&self) -> &str {
9346a6ac 406 "invalid utf-8: corrupt contents"
c34b1796
AL
407 }
408}
409
410#[stable(feature = "rust1", since = "1.0.0")]
411impl Error for num::ParseIntError {
dfeec247 412 #[allow(deprecated)]
c34b1796 413 fn description(&self) -> &str {
62682a34 414 self.__description()
c34b1796
AL
415 }
416}
417
9fa01778 418#[stable(feature = "try_from", since = "1.34.0")]
a7813a04 419impl Error for num::TryFromIntError {
dfeec247 420 #[allow(deprecated)]
a7813a04
XL
421 fn description(&self) -> &str {
422 self.__description()
423 }
424}
425
9fa01778 426#[stable(feature = "try_from", since = "1.34.0")]
abe05a73 427impl Error for array::TryFromSliceError {
dfeec247 428 #[allow(deprecated)]
abe05a73
XL
429 fn description(&self) -> &str {
430 self.__description()
431 }
432}
433
c34b1796
AL
434#[stable(feature = "rust1", since = "1.0.0")]
435impl Error for num::ParseFloatError {
dfeec247 436 #[allow(deprecated)]
c34b1796 437 fn description(&self) -> &str {
d9579d0f 438 self.__description()
c34b1796
AL
439 }
440}
441
442#[stable(feature = "rust1", since = "1.0.0")]
443impl Error for string::FromUtf8Error {
dfeec247 444 #[allow(deprecated)]
c34b1796
AL
445 fn description(&self) -> &str {
446 "invalid utf-8"
447 }
448}
449
450#[stable(feature = "rust1", since = "1.0.0")]
451impl Error for string::FromUtf16Error {
dfeec247 452 #[allow(deprecated)]
c34b1796
AL
453 fn description(&self) -> &str {
454 "invalid utf-16"
455 }
456}
457
7453a54e 458#[stable(feature = "str_parse_error2", since = "1.8.0")]
f9f354fc 459impl Error for Infallible {
7453a54e
SL
460 fn description(&self) -> &str {
461 match *self {}
462 }
463}
464
54a0048b
SL
465#[stable(feature = "decode_utf16", since = "1.9.0")]
466impl Error for char::DecodeUtf16Error {
dfeec247 467 #[allow(deprecated)]
54a0048b
SL
468 fn description(&self) -> &str {
469 "unpaired surrogate found"
470 }
471}
472
6a06907d
XL
473#[unstable(feature = "map_try_insert", issue = "82766")]
474impl<'a, K: Debug + Ord, V: Debug> Error
475 for crate::collections::btree_map::OccupiedError<'a, K, V>
476{
477 #[allow(deprecated)]
478 fn description(&self) -> &str {
479 "key already exists"
480 }
481}
482
483#[unstable(feature = "map_try_insert", issue = "82766")]
484impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> {
485 #[allow(deprecated)]
486 fn description(&self) -> &str {
487 "key already exists"
488 }
489}
490
7cac9316 491#[stable(feature = "box_error", since = "1.8.0")]
7453a54e 492impl<T: Error> Error for Box<T> {
dfeec247 493 #[allow(deprecated, deprecated_in_future)]
7453a54e
SL
494 fn description(&self) -> &str {
495 Error::description(&**self)
496 }
497
0731742a 498 #[allow(deprecated)]
8faf50e0 499 fn cause(&self) -> Option<&dyn Error> {
7453a54e
SL
500 Error::cause(&**self)
501 }
dc9dc135
XL
502
503 fn source(&self) -> Option<&(dyn Error + 'static)> {
504 Error::source(&**self)
505 }
7453a54e
SL
506}
507
5869c6ff
XL
508#[stable(feature = "error_by_ref", since = "1.51.0")]
509impl<'a, T: Error + ?Sized> Error for &'a T {
510 #[allow(deprecated, deprecated_in_future)]
511 fn description(&self) -> &str {
512 Error::description(&**self)
513 }
514
515 #[allow(deprecated)]
516 fn cause(&self) -> Option<&dyn Error> {
517 Error::cause(&**self)
518 }
519
520 fn source(&self) -> Option<&(dyn Error + 'static)> {
521 Error::source(&**self)
522 }
523
524 fn backtrace(&self) -> Option<&Backtrace> {
525 Error::backtrace(&**self)
526 }
527}
528
6a06907d
XL
529#[stable(feature = "arc_error", since = "1.52.0")]
530impl<T: Error + ?Sized> Error for Arc<T> {
531 #[allow(deprecated, deprecated_in_future)]
532 fn description(&self) -> &str {
533 Error::description(&**self)
534 }
535
536 #[allow(deprecated)]
537 fn cause(&self) -> Option<&dyn Error> {
538 Error::cause(&**self)
539 }
540
541 fn source(&self) -> Option<&(dyn Error + 'static)> {
542 Error::source(&**self)
543 }
544
545 fn backtrace(&self) -> Option<&Backtrace> {
546 Error::backtrace(&**self)
547 }
548}
549
3157f602
XL
550#[stable(feature = "fmt_error", since = "1.11.0")]
551impl Error for fmt::Error {
dfeec247 552 #[allow(deprecated)]
3157f602
XL
553 fn description(&self) -> &str {
554 "an error occurred when formatting an argument"
555 }
556}
557
9e0c209e
SL
558#[stable(feature = "try_borrow", since = "1.13.0")]
559impl Error for cell::BorrowError {
dfeec247 560 #[allow(deprecated)]
5bcae85e
SL
561 fn description(&self) -> &str {
562 "already mutably borrowed"
563 }
564}
565
9e0c209e
SL
566#[stable(feature = "try_borrow", since = "1.13.0")]
567impl Error for cell::BorrowMutError {
dfeec247 568 #[allow(deprecated)]
5bcae85e
SL
569 fn description(&self) -> &str {
570 "already borrowed"
571 }
572}
573
9fa01778 574#[stable(feature = "try_from", since = "1.34.0")]
9e0c209e 575impl Error for char::CharTryFromError {
dfeec247 576 #[allow(deprecated)]
9e0c209e
SL
577 fn description(&self) -> &str {
578 "converted integer out of range for `char`"
579 }
580}
581
041b39d2
XL
582#[stable(feature = "char_from_str", since = "1.20.0")]
583impl Error for char::ParseCharError {
dfeec247 584 #[allow(deprecated)]
041b39d2
XL
585 fn description(&self) -> &str {
586 self.__description()
587 }
588}
589
ba9703b0
XL
590#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
591impl Error for alloc::collections::TryReserveError {}
592
e1599b0c 593// Copied from `any.rs`.
8faf50e0 594impl dyn Error + 'static {
9fa01778 595 /// Returns `true` if the boxed type is the same as `T`
c1a9b12d 596 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
597 #[inline]
598 pub fn is<T: Error + 'static>(&self) -> bool {
e1599b0c 599 // Get `TypeId` of the type this function is instantiated with.
bd371182
AL
600 let t = TypeId::of::<T>();
601
e1599b0c 602 // Get `TypeId` of the type in the trait object.
48663c56 603 let boxed = self.type_id(private::Internal);
bd371182 604
e1599b0c 605 // Compare both `TypeId`s on equality.
bd371182
AL
606 t == boxed
607 }
608
609 /// Returns some reference to the boxed value if it is of type `T`, or
610 /// `None` if it isn't.
c1a9b12d 611 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
612 #[inline]
613 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
614 if self.is::<T>() {
dfeec247 615 unsafe { Some(&*(self as *const dyn Error as *const T)) }
bd371182
AL
616 } else {
617 None
618 }
619 }
620
621 /// Returns some mutable reference to the boxed value if it is of type `T`, or
622 /// `None` if it isn't.
c1a9b12d 623 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
624 #[inline]
625 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
626 if self.is::<T>() {
dfeec247 627 unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) }
bd371182
AL
628 } else {
629 None
630 }
631 }
632}
633
8faf50e0 634impl dyn Error + 'static + Send {
e1599b0c 635 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d 636 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
637 #[inline]
638 pub fn is<T: Error + 'static>(&self) -> bool {
8faf50e0 639 <dyn Error + 'static>::is::<T>(self)
bd371182
AL
640 }
641
e1599b0c 642 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d 643 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
644 #[inline]
645 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
8faf50e0 646 <dyn Error + 'static>::downcast_ref::<T>(self)
bd371182
AL
647 }
648
e1599b0c 649 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d
SL
650 #[stable(feature = "error_downcast", since = "1.3.0")]
651 #[inline]
652 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
8faf50e0 653 <dyn Error + 'static>::downcast_mut::<T>(self)
c1a9b12d
SL
654 }
655}
656
8faf50e0 657impl dyn Error + 'static + Send + Sync {
e1599b0c 658 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d
SL
659 #[stable(feature = "error_downcast", since = "1.3.0")]
660 #[inline]
661 pub fn is<T: Error + 'static>(&self) -> bool {
8faf50e0 662 <dyn Error + 'static>::is::<T>(self)
c1a9b12d
SL
663 }
664
e1599b0c 665 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d
SL
666 #[stable(feature = "error_downcast", since = "1.3.0")]
667 #[inline]
668 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
8faf50e0 669 <dyn Error + 'static>::downcast_ref::<T>(self)
c1a9b12d
SL
670 }
671
e1599b0c 672 /// Forwards to the method defined on the type `dyn Error`.
c1a9b12d 673 #[stable(feature = "error_downcast", since = "1.3.0")]
bd371182
AL
674 #[inline]
675 pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
8faf50e0 676 <dyn Error + 'static>::downcast_mut::<T>(self)
bd371182
AL
677 }
678}
679
8faf50e0 680impl dyn Error {
bd371182 681 #[inline]
c1a9b12d 682 #[stable(feature = "error_downcast", since = "1.3.0")]
e1599b0c 683 /// Attempts to downcast the box to a concrete type.
8faf50e0 684 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
bd371182
AL
685 if self.is::<T>() {
686 unsafe {
8faf50e0 687 let raw: *mut dyn Error = Box::into_raw(self);
9e0c209e 688 Ok(Box::from_raw(raw as *mut T))
bd371182
AL
689 }
690 } else {
691 Err(self)
692 }
693 }
9fa01778
XL
694
695 /// Returns an iterator starting with the current error and continuing with
1b1a35ee 696 /// recursively calling [`Error::source`].
9fa01778 697 ///
60c5eb7d
XL
698 /// If you want to omit the current error and only use its sources,
699 /// use `skip(1)`.
700 ///
9fa01778
XL
701 /// # Examples
702 ///
703 /// ```
704 /// #![feature(error_iter)]
705 /// use std::error::Error;
706 /// use std::fmt;
707 ///
708 /// #[derive(Debug)]
709 /// struct A;
710 ///
711 /// #[derive(Debug)]
712 /// struct B(Option<Box<dyn Error + 'static>>);
713 ///
714 /// impl fmt::Display for A {
532ac7d7 715 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9fa01778
XL
716 /// write!(f, "A")
717 /// }
718 /// }
719 ///
720 /// impl fmt::Display for B {
532ac7d7 721 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9fa01778
XL
722 /// write!(f, "B")
723 /// }
724 /// }
725 ///
726 /// impl Error for A {}
727 ///
728 /// impl Error for B {
729 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
730 /// self.0.as_ref().map(|e| e.as_ref())
731 /// }
732 /// }
733 ///
734 /// let b = B(Some(Box::new(A)));
735 ///
736 /// // let err : Box<Error> = b.into(); // or
737 /// let err = &b as &(dyn Error);
738 ///
60c5eb7d 739 /// let mut iter = err.chain();
9fa01778
XL
740 ///
741 /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
742 /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
743 /// assert!(iter.next().is_none());
744 /// assert!(iter.next().is_none());
745 /// ```
9fa01778
XL
746 #[unstable(feature = "error_iter", issue = "58520")]
747 #[inline]
60c5eb7d 748 pub fn chain(&self) -> Chain<'_> {
dfeec247 749 Chain { current: Some(self) }
9fa01778 750 }
9fa01778
XL
751}
752
60c5eb7d
XL
753/// An iterator over an [`Error`] and its sources.
754///
755/// If you want to omit the initial error and only process
756/// its sources, use `skip(1)`.
9fa01778 757#[unstable(feature = "error_iter", issue = "58520")]
60c5eb7d
XL
758#[derive(Clone, Debug)]
759pub struct Chain<'a> {
9fa01778
XL
760 current: Option<&'a (dyn Error + 'static)>,
761}
762
763#[unstable(feature = "error_iter", issue = "58520")]
60c5eb7d 764impl<'a> Iterator for Chain<'a> {
9fa01778
XL
765 type Item = &'a (dyn Error + 'static);
766
767 fn next(&mut self) -> Option<Self::Item> {
768 let current = self.current;
769 self.current = self.current.and_then(Error::source);
770 current
771 }
bd371182
AL
772}
773
8faf50e0 774impl dyn Error + Send {
bd371182 775 #[inline]
c1a9b12d 776 #[stable(feature = "error_downcast", since = "1.3.0")]
e1599b0c 777 /// Attempts to downcast the box to a concrete type.
dfeec247 778 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
8faf50e0
XL
779 let err: Box<dyn Error> = self;
780 <dyn Error>::downcast(err).map_err(|s| unsafe {
e1599b0c 781 // Reapply the `Send` marker.
8faf50e0 782 transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
bd371182
AL
783 })
784 }
785}
c1a9b12d 786
8faf50e0 787impl dyn Error + Send + Sync {
c1a9b12d
SL
788 #[inline]
789 #[stable(feature = "error_downcast", since = "1.3.0")]
e1599b0c 790 /// Attempts to downcast the box to a concrete type.
dfeec247 791 pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
8faf50e0
XL
792 let err: Box<dyn Error> = self;
793 <dyn Error>::downcast(err).map_err(|s| unsafe {
e1599b0c 794 // Reapply the `Send + Sync` marker.
8faf50e0 795 transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
c1a9b12d
SL
796 })
797 }
798}