]>
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 | ||
abe05a73 | 16 | use core::array; |
532ac7d7 | 17 | |
dfeec247 | 18 | use crate::alloc::{AllocErr, CannotReallocInPlace, LayoutErr}; |
532ac7d7 | 19 | use crate::any::TypeId; |
e1599b0c | 20 | use crate::backtrace::Backtrace; |
532ac7d7 XL |
21 | use crate::borrow::Cow; |
22 | use crate::cell; | |
23 | use crate::char; | |
24 | use crate::fmt::{self, Debug, Display}; | |
25 | use crate::mem::transmute; | |
26 | use crate::num; | |
27 | use crate::str; | |
28 | use 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 | 47 | pub 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 |
154 | mod 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 | 163 | impl<'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 | 197 | impl<'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 | 237 | impl 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 | 282 | impl 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 | 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 | /// |
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 | 328 | impl 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 | 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 | 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 | 373 | impl<'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 |
396 | impl 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 | )] | |
403 | impl 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 | )] | |
410 | impl 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 | )] | |
417 | impl Error for CannotReallocInPlace {} | |
041b39d2 | 418 | |
c34b1796 AL |
419 | #[stable(feature = "rust1", since = "1.0.0")] |
420 | impl 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")] | |
428 | impl 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")] | |
436 | impl 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 | 444 | impl 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 | 452 | impl 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")] |
460 | impl 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")] | |
468 | impl 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")] | |
476 | impl 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")] |
484 | impl 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")] |
491 | impl 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 | 499 | impl<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")] |
516 | impl 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")] |
524 | impl 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")] |
532 | impl 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 | 540 | impl 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")] |
548 | impl 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 | 556 | impl 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 | 596 | impl 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 | 619 | impl 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 | 642 | impl 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)] |
725 | pub struct Chain<'a> { | |
9fa01778 XL |
726 | current: Option<&'a (dyn Error + 'static)>, |
727 | } | |
728 | ||
729 | #[unstable(feature = "error_iter", issue = "58520")] | |
60c5eb7d | 730 | impl<'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 | 740 | impl 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 | 753 | impl 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)] | |
767 | mod 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 | } |