]> git.lizzy.rs Git - rust.git/blob - src/libstd/error.rs
Bump to 1.33.0
[rust.git] / src / libstd / error.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Traits for working with Errors.
12
13 #![stable(feature = "rust1", since = "1.0.0")]
14
15 // A note about crates and the facade:
16 //
17 // Originally, the `Error` trait was defined in libcore, and the impls
18 // were scattered about. However, coherence objected to this
19 // arrangement, because to create the blanket impls for `Box` required
20 // knowing that `&str: !Error`, and we have no means to deal with that
21 // sort of conflict just now. Therefore, for the time being, we have
22 // moved the `Error` trait into libstd. As we evolve a sol'n to the
23 // coherence challenge (e.g., specialization, neg impls, etc) we can
24 // reconsider what crate these items belong in.
25
26 use alloc::{AllocErr, LayoutErr, CannotReallocInPlace};
27 use any::TypeId;
28 use borrow::Cow;
29 use cell;
30 use char;
31 use core::array;
32 use fmt::{self, Debug, Display};
33 use mem::transmute;
34 use num;
35 use str;
36 use string;
37
38 /// `Error` is a trait representing the basic expectations for error values,
39 /// i.e., values of type `E` in [`Result<T, E>`]. Errors must describe
40 /// themselves through the [`Display`] and [`Debug`] traits, and may provide
41 /// cause chain information:
42 ///
43 /// The [`cause`] method is generally used when errors cross "abstraction
44 /// boundaries", i.e.,  when a one module must report an error that is "caused"
45 /// by an error from a lower-level module. This setup makes it possible for the
46 /// high-level module to provide its own errors that do not commit to any
47 /// particular implementation, but also reveal some of its implementation for
48 /// debugging via [`cause`] chains.
49 ///
50 /// [`Result<T, E>`]: ../result/enum.Result.html
51 /// [`Display`]: ../fmt/trait.Display.html
52 /// [`Debug`]: ../fmt/trait.Debug.html
53 /// [`cause`]: trait.Error.html#method.cause
54 #[stable(feature = "rust1", since = "1.0.0")]
55 pub trait Error: Debug + Display {
56     /// **This method is soft-deprecated.**
57     ///
58     /// Although using it won’t cause compilation warning,
59     /// new code should use [`Display`] instead
60     /// and new `impl`s can omit it.
61     ///
62     /// To obtain error description as a string, use `to_string()`.
63     ///
64     /// [`Display`]: ../fmt/trait.Display.html
65     ///
66     /// # Examples
67     ///
68     /// ```
69     /// match "xc".parse::<u32>() {
70     ///     Err(e) => {
71     ///         // Print `e` itself, not `e.description()`.
72     ///         println!("Error: {}", e);
73     ///     }
74     ///     _ => println!("No error"),
75     /// }
76     /// ```
77     #[stable(feature = "rust1", since = "1.0.0")]
78     fn description(&self) -> &str {
79         "description() is deprecated; use Display"
80     }
81
82     /// The lower-level cause of this error, if any.
83     ///
84     /// # Examples
85     ///
86     /// ```
87     /// use std::error::Error;
88     /// use std::fmt;
89     ///
90     /// #[derive(Debug)]
91     /// struct SuperError {
92     ///     side: SuperErrorSideKick,
93     /// }
94     ///
95     /// impl fmt::Display for SuperError {
96     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97     ///         write!(f, "SuperError is here!")
98     ///     }
99     /// }
100     ///
101     /// impl Error for SuperError {
102     ///     fn description(&self) -> &str {
103     ///         "I'm the superhero of errors"
104     ///     }
105     ///
106     ///     fn cause(&self) -> Option<&Error> {
107     ///         Some(&self.side)
108     ///     }
109     /// }
110     ///
111     /// #[derive(Debug)]
112     /// struct SuperErrorSideKick;
113     ///
114     /// impl fmt::Display for SuperErrorSideKick {
115     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116     ///         write!(f, "SuperErrorSideKick is here!")
117     ///     }
118     /// }
119     ///
120     /// impl Error for SuperErrorSideKick {
121     ///     fn description(&self) -> &str {
122     ///         "I'm SuperError side kick"
123     ///     }
124     /// }
125     ///
126     /// fn get_super_error() -> Result<(), SuperError> {
127     ///     Err(SuperError { side: SuperErrorSideKick })
128     /// }
129     ///
130     /// fn main() {
131     ///     match get_super_error() {
132     ///         Err(e) => {
133     ///             println!("Error: {}", e.description());
134     ///             println!("Caused by: {}", e.cause().unwrap());
135     ///         }
136     ///         _ => println!("No error"),
137     ///     }
138     /// }
139     /// ```
140     #[stable(feature = "rust1", since = "1.0.0")]
141     #[rustc_deprecated(since = "1.33.0", reason = "replaced by Error::source, which can support \
142                                                    downcasting")]
143     fn cause(&self) -> Option<&dyn Error> {
144         self.source()
145     }
146
147     /// The lower-level source of this error, if any.
148     ///
149     /// # Examples
150     ///
151     /// ```
152     /// use std::error::Error;
153     /// use std::fmt;
154     ///
155     /// #[derive(Debug)]
156     /// struct SuperError {
157     ///     side: SuperErrorSideKick,
158     /// }
159     ///
160     /// impl fmt::Display for SuperError {
161     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162     ///         write!(f, "SuperError is here!")
163     ///     }
164     /// }
165     ///
166     /// impl Error for SuperError {
167     ///     fn description(&self) -> &str {
168     ///         "I'm the superhero of errors"
169     ///     }
170     ///
171     ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
172     ///         Some(&self.side)
173     ///     }
174     /// }
175     ///
176     /// #[derive(Debug)]
177     /// struct SuperErrorSideKick;
178     ///
179     /// impl fmt::Display for SuperErrorSideKick {
180     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181     ///         write!(f, "SuperErrorSideKick is here!")
182     ///     }
183     /// }
184     ///
185     /// impl Error for SuperErrorSideKick {
186     ///     fn description(&self) -> &str {
187     ///         "I'm SuperError side kick"
188     ///     }
189     /// }
190     ///
191     /// fn get_super_error() -> Result<(), SuperError> {
192     ///     Err(SuperError { side: SuperErrorSideKick })
193     /// }
194     ///
195     /// fn main() {
196     ///     match get_super_error() {
197     ///         Err(e) => {
198     ///             println!("Error: {}", e.description());
199     ///             println!("Caused by: {}", e.source().unwrap());
200     ///         }
201     ///         _ => println!("No error"),
202     ///     }
203     /// }
204     /// ```
205     #[stable(feature = "error_source", since = "1.30.0")]
206     fn source(&self) -> Option<&(dyn Error + 'static)> { None }
207
208     /// Get the `TypeId` of `self`
209     #[doc(hidden)]
210     #[unstable(feature = "error_type_id",
211                reason = "unclear whether to commit to this public implementation detail",
212                issue = "27745")]
213     fn type_id(&self) -> TypeId where Self: 'static {
214         TypeId::of::<Self>()
215     }
216 }
217
218 #[stable(feature = "rust1", since = "1.0.0")]
219 impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
220     /// Converts a type of [`Error`] into a box of dyn [`Error`].
221     ///
222     /// # Examples
223     ///
224     /// ```
225     /// use std::error::Error;
226     /// use std::fmt;
227     /// use std::mem;
228     ///
229     /// #[derive(Debug)]
230     /// struct AnError;
231     ///
232     /// impl fmt::Display for AnError {
233     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234     ///         write!(f , "An error")
235     ///     }
236     /// }
237     ///
238     /// impl Error for AnError {
239     ///     fn description(&self) -> &str {
240     ///         "Description of an error"
241     ///     }
242     /// }
243     ///
244     /// let an_error = AnError;
245     /// assert!(0 == mem::size_of_val(&an_error));
246     /// let a_boxed_error = Box::<Error>::from(an_error);
247     /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
248     /// ```
249     fn from(err: E) -> Box<dyn Error + 'a> {
250         Box::new(err)
251     }
252 }
253
254 #[stable(feature = "rust1", since = "1.0.0")]
255 impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
256     /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] +
257     /// [`Send`] + [`Sync`].
258     ///
259     /// # Examples
260     ///
261     /// ```
262     /// use std::error::Error;
263     /// use std::fmt;
264     /// use std::mem;
265     ///
266     /// #[derive(Debug)]
267     /// struct AnError;
268     ///
269     /// impl fmt::Display for AnError {
270     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
271     ///         write!(f , "An error")
272     ///     }
273     /// }
274     ///
275     /// impl Error for AnError {
276     ///     fn description(&self) -> &str {
277     ///         "Description of an error"
278     ///     }
279     /// }
280     ///
281     /// unsafe impl Send for AnError {}
282     ///
283     /// unsafe impl Sync for AnError {}
284     ///
285     /// let an_error = AnError;
286     /// assert!(0 == mem::size_of_val(&an_error));
287     /// let a_boxed_error = Box::<Error + Send + Sync>::from(an_error);
288     /// assert!(
289     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
290     /// ```
291     fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
292         Box::new(err)
293     }
294 }
295
296 #[stable(feature = "rust1", since = "1.0.0")]
297 impl From<String> for Box<dyn Error + Send + Sync> {
298     /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
299     ///
300     /// # Examples
301     ///
302     /// ```
303     /// use std::error::Error;
304     /// use std::mem;
305     ///
306     /// let a_string_error = "a string error".to_string();
307     /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_string_error);
308     /// assert!(
309     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
310     /// ```
311     fn from(err: String) -> Box<dyn Error + Send + Sync> {
312         #[derive(Debug)]
313         struct StringError(String);
314
315         impl Error for StringError {
316             fn description(&self) -> &str { &self.0 }
317         }
318
319         impl Display for StringError {
320             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
321                 Display::fmt(&self.0, f)
322             }
323         }
324
325         Box::new(StringError(err))
326     }
327 }
328
329 #[stable(feature = "string_box_error", since = "1.6.0")]
330 impl From<String> for Box<dyn Error> {
331     /// Converts a [`String`] into a box of dyn [`Error`].
332     ///
333     /// # Examples
334     ///
335     /// ```
336     /// use std::error::Error;
337     /// use std::mem;
338     ///
339     /// let a_string_error = "a string error".to_string();
340     /// let a_boxed_error = Box::<Error>::from(a_string_error);
341     /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
342     /// ```
343     fn from(str_err: String) -> Box<dyn Error> {
344         let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
345         let err2: Box<dyn Error> = err1;
346         err2
347     }
348 }
349
350 #[stable(feature = "rust1", since = "1.0.0")]
351 impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
352     /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
353     ///
354     /// # Examples
355     ///
356     /// ```
357     /// use std::error::Error;
358     /// use std::mem;
359     ///
360     /// let a_str_error = "a str error";
361     /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_str_error);
362     /// assert!(
363     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
364     /// ```
365     fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
366         From::from(String::from(err))
367     }
368 }
369
370 #[stable(feature = "string_box_error", since = "1.6.0")]
371 impl<'a> From<&'a str> for Box<dyn Error> {
372     /// Converts a [`str`] into a box of dyn [`Error`].
373     ///
374     /// # Examples
375     ///
376     /// ```
377     /// use std::error::Error;
378     /// use std::mem;
379     ///
380     /// let a_str_error = "a str error";
381     /// let a_boxed_error = Box::<Error>::from(a_str_error);
382     /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
383     /// ```
384     fn from(err: &'a str) -> Box<dyn Error> {
385         From::from(String::from(err))
386     }
387 }
388
389 #[stable(feature = "cow_box_error", since = "1.22.0")]
390 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
391     /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
392     ///
393     /// # Examples
394     ///
395     /// ```
396     /// use std::error::Error;
397     /// use std::mem;
398     /// use std::borrow::Cow;
399     ///
400     /// let a_cow_str_error = Cow::from("a str error");
401     /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_cow_str_error);
402     /// assert!(
403     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
404     /// ```
405     fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
406         From::from(String::from(err))
407     }
408 }
409
410 #[stable(feature = "cow_box_error", since = "1.22.0")]
411 impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
412     /// Converts a [`Cow`] into a box of dyn [`Error`].
413     ///
414     /// # Examples
415     ///
416     /// ```
417     /// use std::error::Error;
418     /// use std::mem;
419     /// use std::borrow::Cow;
420     ///
421     /// let a_cow_str_error = Cow::from("a str error");
422     /// let a_boxed_error = Box::<Error>::from(a_cow_str_error);
423     /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
424     /// ```
425     fn from(err: Cow<'a, str>) -> Box<dyn Error> {
426         From::from(String::from(err))
427     }
428 }
429
430 #[unstable(feature = "never_type", issue = "35121")]
431 impl Error for ! {
432     fn description(&self) -> &str { *self }
433 }
434
435 #[unstable(feature = "allocator_api",
436            reason = "the precise API and guarantees it provides may be tweaked.",
437            issue = "32838")]
438 impl Error for AllocErr {
439     fn description(&self) -> &str {
440         "memory allocation failed"
441     }
442 }
443
444 #[unstable(feature = "allocator_api",
445            reason = "the precise API and guarantees it provides may be tweaked.",
446            issue = "32838")]
447 impl Error for LayoutErr {
448     fn description(&self) -> &str {
449         "invalid parameters to Layout::from_size_align"
450     }
451 }
452
453 #[unstable(feature = "allocator_api",
454            reason = "the precise API and guarantees it provides may be tweaked.",
455            issue = "32838")]
456 impl Error for CannotReallocInPlace {
457     fn description(&self) -> &str {
458         CannotReallocInPlace::description(self)
459     }
460 }
461
462 #[stable(feature = "rust1", since = "1.0.0")]
463 impl Error for str::ParseBoolError {
464     fn description(&self) -> &str { "failed to parse bool" }
465 }
466
467 #[stable(feature = "rust1", since = "1.0.0")]
468 impl Error for str::Utf8Error {
469     fn description(&self) -> &str {
470         "invalid utf-8: corrupt contents"
471     }
472 }
473
474 #[stable(feature = "rust1", since = "1.0.0")]
475 impl Error for num::ParseIntError {
476     fn description(&self) -> &str {
477         self.__description()
478     }
479 }
480
481 #[unstable(feature = "try_from", issue = "33417")]
482 impl Error for num::TryFromIntError {
483     fn description(&self) -> &str {
484         self.__description()
485     }
486 }
487
488 #[unstable(feature = "try_from", issue = "33417")]
489 impl Error for array::TryFromSliceError {
490     fn description(&self) -> &str {
491         self.__description()
492     }
493 }
494
495 #[stable(feature = "rust1", since = "1.0.0")]
496 impl Error for num::ParseFloatError {
497     fn description(&self) -> &str {
498         self.__description()
499     }
500 }
501
502 #[stable(feature = "rust1", since = "1.0.0")]
503 impl Error for string::FromUtf8Error {
504     fn description(&self) -> &str {
505         "invalid utf-8"
506     }
507 }
508
509 #[stable(feature = "rust1", since = "1.0.0")]
510 impl Error for string::FromUtf16Error {
511     fn description(&self) -> &str {
512         "invalid utf-16"
513     }
514 }
515
516 #[stable(feature = "str_parse_error2", since = "1.8.0")]
517 impl Error for string::ParseError {
518     fn description(&self) -> &str {
519         match *self {}
520     }
521 }
522
523 #[stable(feature = "decode_utf16", since = "1.9.0")]
524 impl Error for char::DecodeUtf16Error {
525     fn description(&self) -> &str {
526         "unpaired surrogate found"
527     }
528 }
529
530 #[stable(feature = "box_error", since = "1.8.0")]
531 impl<T: Error> Error for Box<T> {
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
542 #[stable(feature = "fmt_error", since = "1.11.0")]
543 impl Error for fmt::Error {
544     fn description(&self) -> &str {
545         "an error occurred when formatting an argument"
546     }
547 }
548
549 #[stable(feature = "try_borrow", since = "1.13.0")]
550 impl Error for cell::BorrowError {
551     fn description(&self) -> &str {
552         "already mutably borrowed"
553     }
554 }
555
556 #[stable(feature = "try_borrow", since = "1.13.0")]
557 impl Error for cell::BorrowMutError {
558     fn description(&self) -> &str {
559         "already borrowed"
560     }
561 }
562
563 #[unstable(feature = "try_from", issue = "33417")]
564 impl Error for char::CharTryFromError {
565     fn description(&self) -> &str {
566         "converted integer out of range for `char`"
567     }
568 }
569
570 #[stable(feature = "char_from_str", since = "1.20.0")]
571 impl Error for char::ParseCharError {
572     fn description(&self) -> &str {
573         self.__description()
574     }
575 }
576
577 // copied from any.rs
578 impl dyn Error + 'static {
579     /// Returns true if the boxed type is the same as `T`
580     #[stable(feature = "error_downcast", since = "1.3.0")]
581     #[inline]
582     pub fn is<T: Error + 'static>(&self) -> bool {
583         // Get TypeId of the type this function is instantiated with
584         let t = TypeId::of::<T>();
585
586         // Get TypeId of the type in the trait object
587         let boxed = self.type_id();
588
589         // Compare both TypeIds on equality
590         t == boxed
591     }
592
593     /// Returns some reference to the boxed value if it is of type `T`, or
594     /// `None` if it isn't.
595     #[stable(feature = "error_downcast", since = "1.3.0")]
596     #[inline]
597     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
598         if self.is::<T>() {
599             unsafe {
600                 Some(&*(self as *const dyn Error as *const T))
601             }
602         } else {
603             None
604         }
605     }
606
607     /// Returns some mutable reference to the boxed value if it is of type `T`, or
608     /// `None` if it isn't.
609     #[stable(feature = "error_downcast", since = "1.3.0")]
610     #[inline]
611     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
612         if self.is::<T>() {
613             unsafe {
614                 Some(&mut *(self as *mut dyn Error as *mut T))
615             }
616         } else {
617             None
618         }
619     }
620 }
621
622 impl dyn Error + 'static + Send {
623     /// Forwards to the method defined on the type `Any`.
624     #[stable(feature = "error_downcast", since = "1.3.0")]
625     #[inline]
626     pub fn is<T: Error + 'static>(&self) -> bool {
627         <dyn Error + 'static>::is::<T>(self)
628     }
629
630     /// Forwards to the method defined on the type `Any`.
631     #[stable(feature = "error_downcast", since = "1.3.0")]
632     #[inline]
633     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
634         <dyn Error + 'static>::downcast_ref::<T>(self)
635     }
636
637     /// Forwards to the method defined on the type `Any`.
638     #[stable(feature = "error_downcast", since = "1.3.0")]
639     #[inline]
640     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
641         <dyn Error + 'static>::downcast_mut::<T>(self)
642     }
643 }
644
645 impl dyn Error + 'static + Send + Sync {
646     /// Forwards to the method defined on the type `Any`.
647     #[stable(feature = "error_downcast", since = "1.3.0")]
648     #[inline]
649     pub fn is<T: Error + 'static>(&self) -> bool {
650         <dyn Error + 'static>::is::<T>(self)
651     }
652
653     /// Forwards to the method defined on the type `Any`.
654     #[stable(feature = "error_downcast", since = "1.3.0")]
655     #[inline]
656     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
657         <dyn Error + 'static>::downcast_ref::<T>(self)
658     }
659
660     /// Forwards to the method defined on the type `Any`.
661     #[stable(feature = "error_downcast", since = "1.3.0")]
662     #[inline]
663     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
664         <dyn Error + 'static>::downcast_mut::<T>(self)
665     }
666 }
667
668 impl dyn Error {
669     #[inline]
670     #[stable(feature = "error_downcast", since = "1.3.0")]
671     /// Attempt to downcast the box to a concrete type.
672     pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
673         if self.is::<T>() {
674             unsafe {
675                 let raw: *mut dyn Error = Box::into_raw(self);
676                 Ok(Box::from_raw(raw as *mut T))
677             }
678         } else {
679             Err(self)
680         }
681     }
682 }
683
684 impl dyn Error + Send {
685     #[inline]
686     #[stable(feature = "error_downcast", since = "1.3.0")]
687     /// Attempt to downcast the box to a concrete type.
688     pub fn downcast<T: Error + 'static>(self: Box<Self>)
689                                         -> Result<Box<T>, Box<dyn Error + Send>> {
690         let err: Box<dyn Error> = self;
691         <dyn Error>::downcast(err).map_err(|s| unsafe {
692             // reapply the Send marker
693             transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
694         })
695     }
696 }
697
698 impl dyn Error + Send + Sync {
699     #[inline]
700     #[stable(feature = "error_downcast", since = "1.3.0")]
701     /// Attempt to downcast the box to a concrete type.
702     pub fn downcast<T: Error + 'static>(self: Box<Self>)
703                                         -> Result<Box<T>, Box<Self>> {
704         let err: Box<dyn Error> = self;
705         <dyn Error>::downcast(err).map_err(|s| unsafe {
706             // reapply the Send+Sync marker
707             transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
708         })
709     }
710 }
711
712 #[cfg(test)]
713 mod tests {
714     use super::Error;
715     use fmt;
716
717     #[derive(Debug, PartialEq)]
718     struct A;
719     #[derive(Debug, PartialEq)]
720     struct B;
721
722     impl fmt::Display for A {
723         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
724             write!(f, "A")
725         }
726     }
727     impl fmt::Display for B {
728         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
729             write!(f, "B")
730         }
731     }
732
733     impl Error for A {
734         fn description(&self) -> &str { "A-desc" }
735     }
736     impl Error for B {
737         fn description(&self) -> &str { "A-desc" }
738     }
739
740     #[test]
741     fn downcasting() {
742         let mut a = A;
743         let a = &mut a as &mut (dyn Error + 'static);
744         assert_eq!(a.downcast_ref::<A>(), Some(&A));
745         assert_eq!(a.downcast_ref::<B>(), None);
746         assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
747         assert_eq!(a.downcast_mut::<B>(), None);
748
749         let a: Box<dyn Error> = Box::new(A);
750         match a.downcast::<B>() {
751             Ok(..) => panic!("expected error"),
752             Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
753         }
754     }
755 }