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