]>
Commit | Line | Data |
---|---|---|
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)] |
17 | mod tests; | |
18 | ||
abe05a73 | 19 | use core::array; |
f9f354fc | 20 | use core::convert::Infallible; |
532ac7d7 | 21 | |
fc512014 | 22 | use crate::alloc::{AllocError, LayoutError}; |
532ac7d7 | 23 | use crate::any::TypeId; |
e1599b0c | 24 | use crate::backtrace::Backtrace; |
532ac7d7 XL |
25 | use crate::borrow::Cow; |
26 | use crate::cell; | |
27 | use crate::char; | |
28 | use crate::fmt::{self, Debug, Display}; | |
29 | use crate::mem::transmute; | |
30 | use crate::num; | |
31 | use crate::str; | |
32 | use crate::string; | |
6a06907d | 33 | use crate::sync::Arc; |
c295e0f8 | 34 | use 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 | 55 | pub 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 |
162 | mod 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 | 171 | impl<'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 | 203 | impl<'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 | 241 | impl 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 | 284 | impl 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 | 305 | impl<'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 | 328 | impl 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 | 349 | impl<'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 | 370 | impl<'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 |
390 | impl 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 | 397 | impl Error for AllocError {} |
dfeec247 | 398 | |
1b1a35ee | 399 | #[stable(feature = "alloc_layout", since = "1.28.0")] |
fc512014 | 400 | impl Error for LayoutError {} |
dfeec247 | 401 | |
c34b1796 AL |
402 | #[stable(feature = "rust1", since = "1.0.0")] |
403 | impl 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")] | |
411 | impl 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")] | |
419 | impl 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 | 427 | impl 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 | 435 | impl 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")] |
443 | impl 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")] | |
451 | impl 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")] | |
459 | impl 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 | 467 | impl 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")] |
474 | impl 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")] |
482 | impl Error for char::TryFromCharError {} | |
483 | ||
6a06907d XL |
484 | #[unstable(feature = "map_try_insert", issue = "82766")] |
485 | impl<'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")] | |
495 | impl<'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 | 503 | impl<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")] |
520 | impl<'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")] |
541 | impl<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")] |
562 | impl 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")] |
570 | impl 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")] |
578 | impl 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 | 586 | impl 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")] |
594 | impl 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 |
602 | impl Error for alloc::collections::TryReserveError {} |
603 | ||
136023e0 | 604 | #[unstable(feature = "duration_checked_float", issue = "83400")] |
c295e0f8 | 605 | impl Error for time::FromSecsError {} |
136023e0 | 606 | |
e1599b0c | 607 | // Copied from `any.rs`. |
8faf50e0 | 608 | impl 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 | 648 | impl 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 | 671 | impl 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 | 694 | impl 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)] |
773 | pub struct Chain<'a> { | |
9fa01778 XL |
774 | current: Option<&'a (dyn Error + 'static)>, |
775 | } | |
776 | ||
777 | #[unstable(feature = "error_iter", issue = "58520")] | |
60c5eb7d | 778 | impl<'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 | 788 | impl 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 | 801 | impl 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 | } |