]> git.lizzy.rs Git - rust.git/blob - src/libstd/error.rs
7a5353bb60ff634c68c58cb65811abcaea1beda4
[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     fn cause(&self) -> Option<&dyn Error> {
537         Error::cause(&**self)
538     }
539 }
540
541 #[stable(feature = "fmt_error", since = "1.11.0")]
542 impl Error for fmt::Error {
543     fn description(&self) -> &str {
544         "an error occurred when formatting an argument"
545     }
546 }
547
548 #[stable(feature = "try_borrow", since = "1.13.0")]
549 impl Error for cell::BorrowError {
550     fn description(&self) -> &str {
551         "already mutably borrowed"
552     }
553 }
554
555 #[stable(feature = "try_borrow", since = "1.13.0")]
556 impl Error for cell::BorrowMutError {
557     fn description(&self) -> &str {
558         "already borrowed"
559     }
560 }
561
562 #[unstable(feature = "try_from", issue = "33417")]
563 impl Error for char::CharTryFromError {
564     fn description(&self) -> &str {
565         "converted integer out of range for `char`"
566     }
567 }
568
569 #[stable(feature = "char_from_str", since = "1.20.0")]
570 impl Error for char::ParseCharError {
571     fn description(&self) -> &str {
572         self.__description()
573     }
574 }
575
576 // copied from any.rs
577 impl dyn Error + 'static {
578     /// Returns true if the boxed type is the same as `T`
579     #[stable(feature = "error_downcast", since = "1.3.0")]
580     #[inline]
581     pub fn is<T: Error + 'static>(&self) -> bool {
582         // Get TypeId of the type this function is instantiated with
583         let t = TypeId::of::<T>();
584
585         // Get TypeId of the type in the trait object
586         let boxed = self.type_id();
587
588         // Compare both TypeIds on equality
589         t == boxed
590     }
591
592     /// Returns some reference to the boxed value if it is of type `T`, or
593     /// `None` if it isn't.
594     #[stable(feature = "error_downcast", since = "1.3.0")]
595     #[inline]
596     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
597         if self.is::<T>() {
598             unsafe {
599                 Some(&*(self as *const dyn Error as *const T))
600             }
601         } else {
602             None
603         }
604     }
605
606     /// Returns some mutable reference to the boxed value if it is of type `T`, or
607     /// `None` if it isn't.
608     #[stable(feature = "error_downcast", since = "1.3.0")]
609     #[inline]
610     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
611         if self.is::<T>() {
612             unsafe {
613                 Some(&mut *(self as *mut dyn Error as *mut T))
614             }
615         } else {
616             None
617         }
618     }
619 }
620
621 impl dyn Error + 'static + Send {
622     /// Forwards to the method defined on the type `Any`.
623     #[stable(feature = "error_downcast", since = "1.3.0")]
624     #[inline]
625     pub fn is<T: Error + 'static>(&self) -> bool {
626         <dyn Error + 'static>::is::<T>(self)
627     }
628
629     /// Forwards to the method defined on the type `Any`.
630     #[stable(feature = "error_downcast", since = "1.3.0")]
631     #[inline]
632     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
633         <dyn Error + 'static>::downcast_ref::<T>(self)
634     }
635
636     /// Forwards to the method defined on the type `Any`.
637     #[stable(feature = "error_downcast", since = "1.3.0")]
638     #[inline]
639     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
640         <dyn Error + 'static>::downcast_mut::<T>(self)
641     }
642 }
643
644 impl dyn Error + 'static + Send + Sync {
645     /// Forwards to the method defined on the type `Any`.
646     #[stable(feature = "error_downcast", since = "1.3.0")]
647     #[inline]
648     pub fn is<T: Error + 'static>(&self) -> bool {
649         <dyn Error + 'static>::is::<T>(self)
650     }
651
652     /// Forwards to the method defined on the type `Any`.
653     #[stable(feature = "error_downcast", since = "1.3.0")]
654     #[inline]
655     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
656         <dyn Error + 'static>::downcast_ref::<T>(self)
657     }
658
659     /// Forwards to the method defined on the type `Any`.
660     #[stable(feature = "error_downcast", since = "1.3.0")]
661     #[inline]
662     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
663         <dyn Error + 'static>::downcast_mut::<T>(self)
664     }
665 }
666
667 impl dyn Error {
668     #[inline]
669     #[stable(feature = "error_downcast", since = "1.3.0")]
670     /// Attempt to downcast the box to a concrete type.
671     pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
672         if self.is::<T>() {
673             unsafe {
674                 let raw: *mut dyn Error = Box::into_raw(self);
675                 Ok(Box::from_raw(raw as *mut T))
676             }
677         } else {
678             Err(self)
679         }
680     }
681 }
682
683 impl dyn Error + Send {
684     #[inline]
685     #[stable(feature = "error_downcast", since = "1.3.0")]
686     /// Attempt to downcast the box to a concrete type.
687     pub fn downcast<T: Error + 'static>(self: Box<Self>)
688                                         -> Result<Box<T>, Box<dyn Error + Send>> {
689         let err: Box<dyn Error> = self;
690         <dyn Error>::downcast(err).map_err(|s| unsafe {
691             // reapply the Send marker
692             transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
693         })
694     }
695 }
696
697 impl dyn Error + Send + Sync {
698     #[inline]
699     #[stable(feature = "error_downcast", since = "1.3.0")]
700     /// Attempt to downcast the box to a concrete type.
701     pub fn downcast<T: Error + 'static>(self: Box<Self>)
702                                         -> Result<Box<T>, Box<Self>> {
703         let err: Box<dyn Error> = self;
704         <dyn Error>::downcast(err).map_err(|s| unsafe {
705             // reapply the Send+Sync marker
706             transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
707         })
708     }
709 }
710
711 #[cfg(test)]
712 mod tests {
713     use super::Error;
714     use fmt;
715
716     #[derive(Debug, PartialEq)]
717     struct A;
718     #[derive(Debug, PartialEq)]
719     struct B;
720
721     impl fmt::Display for A {
722         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
723             write!(f, "A")
724         }
725     }
726     impl fmt::Display for B {
727         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
728             write!(f, "B")
729         }
730     }
731
732     impl Error for A {
733         fn description(&self) -> &str { "A-desc" }
734     }
735     impl Error for B {
736         fn description(&self) -> &str { "A-desc" }
737     }
738
739     #[test]
740     fn downcasting() {
741         let mut a = A;
742         let a = &mut a as &mut (dyn Error + 'static);
743         assert_eq!(a.downcast_ref::<A>(), Some(&A));
744         assert_eq!(a.downcast_ref::<B>(), None);
745         assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
746         assert_eq!(a.downcast_mut::<B>(), None);
747
748         let a: Box<dyn Error> = Box::new(A);
749         match a.downcast::<B>() {
750             Ok(..) => panic!("expected error"),
751             Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
752         }
753     }
754 }