]> git.lizzy.rs Git - rust.git/blob - src/libstd/error.rs
Auto merge of #53707 - eddyb:phantom-waffles, r=oli-obk
[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     fn from(err: E) -> Box<dyn Error + 'a> {
221         Box::new(err)
222     }
223 }
224
225 #[stable(feature = "rust1", since = "1.0.0")]
226 impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
227     fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
228         Box::new(err)
229     }
230 }
231
232 #[stable(feature = "rust1", since = "1.0.0")]
233 impl From<String> for Box<dyn Error + Send + Sync> {
234     fn from(err: String) -> Box<dyn Error + Send + Sync> {
235         #[derive(Debug)]
236         struct StringError(String);
237
238         impl Error for StringError {
239             fn description(&self) -> &str { &self.0 }
240         }
241
242         impl Display for StringError {
243             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244                 Display::fmt(&self.0, f)
245             }
246         }
247
248         Box::new(StringError(err))
249     }
250 }
251
252 #[stable(feature = "string_box_error", since = "1.6.0")]
253 impl From<String> for Box<dyn Error> {
254     fn from(str_err: String) -> Box<dyn Error> {
255         let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
256         let err2: Box<dyn Error> = err1;
257         err2
258     }
259 }
260
261 #[stable(feature = "rust1", since = "1.0.0")]
262 impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
263     fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
264         From::from(String::from(err))
265     }
266 }
267
268 #[stable(feature = "string_box_error", since = "1.6.0")]
269 impl<'a> From<&'a str> for Box<dyn Error> {
270     fn from(err: &'a str) -> Box<dyn Error> {
271         From::from(String::from(err))
272     }
273 }
274
275 #[stable(feature = "cow_box_error", since = "1.22.0")]
276 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
277     fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
278         From::from(String::from(err))
279     }
280 }
281
282 #[stable(feature = "cow_box_error", since = "1.22.0")]
283 impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
284     fn from(err: Cow<'a, str>) -> Box<dyn Error> {
285         From::from(String::from(err))
286     }
287 }
288
289 #[unstable(feature = "never_type", issue = "35121")]
290 impl Error for ! {
291     fn description(&self) -> &str { *self }
292 }
293
294 #[unstable(feature = "allocator_api",
295            reason = "the precise API and guarantees it provides may be tweaked.",
296            issue = "32838")]
297 impl Error for AllocErr {
298     fn description(&self) -> &str {
299         "memory allocation failed"
300     }
301 }
302
303 #[unstable(feature = "allocator_api",
304            reason = "the precise API and guarantees it provides may be tweaked.",
305            issue = "32838")]
306 impl Error for LayoutErr {
307     fn description(&self) -> &str {
308         "invalid parameters to Layout::from_size_align"
309     }
310 }
311
312 #[unstable(feature = "allocator_api",
313            reason = "the precise API and guarantees it provides may be tweaked.",
314            issue = "32838")]
315 impl Error for CannotReallocInPlace {
316     fn description(&self) -> &str {
317         CannotReallocInPlace::description(self)
318     }
319 }
320
321 #[stable(feature = "rust1", since = "1.0.0")]
322 impl Error for str::ParseBoolError {
323     fn description(&self) -> &str { "failed to parse bool" }
324 }
325
326 #[stable(feature = "rust1", since = "1.0.0")]
327 impl Error for str::Utf8Error {
328     fn description(&self) -> &str {
329         "invalid utf-8: corrupt contents"
330     }
331 }
332
333 #[stable(feature = "rust1", since = "1.0.0")]
334 impl Error for num::ParseIntError {
335     fn description(&self) -> &str {
336         self.__description()
337     }
338 }
339
340 #[unstable(feature = "try_from", issue = "33417")]
341 impl Error for num::TryFromIntError {
342     fn description(&self) -> &str {
343         self.__description()
344     }
345 }
346
347 #[unstable(feature = "try_from", issue = "33417")]
348 impl Error for array::TryFromSliceError {
349     fn description(&self) -> &str {
350         self.__description()
351     }
352 }
353
354 #[stable(feature = "rust1", since = "1.0.0")]
355 impl Error for num::ParseFloatError {
356     fn description(&self) -> &str {
357         self.__description()
358     }
359 }
360
361 #[stable(feature = "rust1", since = "1.0.0")]
362 impl Error for string::FromUtf8Error {
363     fn description(&self) -> &str {
364         "invalid utf-8"
365     }
366 }
367
368 #[stable(feature = "rust1", since = "1.0.0")]
369 impl Error for string::FromUtf16Error {
370     fn description(&self) -> &str {
371         "invalid utf-16"
372     }
373 }
374
375 #[stable(feature = "str_parse_error2", since = "1.8.0")]
376 impl Error for string::ParseError {
377     fn description(&self) -> &str {
378         match *self {}
379     }
380 }
381
382 #[stable(feature = "decode_utf16", since = "1.9.0")]
383 impl Error for char::DecodeUtf16Error {
384     fn description(&self) -> &str {
385         "unpaired surrogate found"
386     }
387 }
388
389 #[stable(feature = "box_error", since = "1.8.0")]
390 impl<T: Error> Error for Box<T> {
391     fn description(&self) -> &str {
392         Error::description(&**self)
393     }
394
395     fn cause(&self) -> Option<&dyn Error> {
396         Error::cause(&**self)
397     }
398 }
399
400 #[stable(feature = "fmt_error", since = "1.11.0")]
401 impl Error for fmt::Error {
402     fn description(&self) -> &str {
403         "an error occurred when formatting an argument"
404     }
405 }
406
407 #[stable(feature = "try_borrow", since = "1.13.0")]
408 impl Error for cell::BorrowError {
409     fn description(&self) -> &str {
410         "already mutably borrowed"
411     }
412 }
413
414 #[stable(feature = "try_borrow", since = "1.13.0")]
415 impl Error for cell::BorrowMutError {
416     fn description(&self) -> &str {
417         "already borrowed"
418     }
419 }
420
421 #[unstable(feature = "try_from", issue = "33417")]
422 impl Error for char::CharTryFromError {
423     fn description(&self) -> &str {
424         "converted integer out of range for `char`"
425     }
426 }
427
428 #[stable(feature = "char_from_str", since = "1.20.0")]
429 impl Error for char::ParseCharError {
430     fn description(&self) -> &str {
431         self.__description()
432     }
433 }
434
435 // copied from any.rs
436 impl dyn Error + 'static {
437     /// Returns true if the boxed type is the same as `T`
438     #[stable(feature = "error_downcast", since = "1.3.0")]
439     #[inline]
440     pub fn is<T: Error + 'static>(&self) -> bool {
441         // Get TypeId of the type this function is instantiated with
442         let t = TypeId::of::<T>();
443
444         // Get TypeId of the type in the trait object
445         let boxed = self.type_id();
446
447         // Compare both TypeIds on equality
448         t == boxed
449     }
450
451     /// Returns some reference to the boxed value if it is of type `T`, or
452     /// `None` if it isn't.
453     #[stable(feature = "error_downcast", since = "1.3.0")]
454     #[inline]
455     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
456         if self.is::<T>() {
457             unsafe {
458                 Some(&*(self as *const dyn Error as *const T))
459             }
460         } else {
461             None
462         }
463     }
464
465     /// Returns some mutable reference to the boxed value if it is of type `T`, or
466     /// `None` if it isn't.
467     #[stable(feature = "error_downcast", since = "1.3.0")]
468     #[inline]
469     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
470         if self.is::<T>() {
471             unsafe {
472                 Some(&mut *(self as *mut dyn Error as *mut T))
473             }
474         } else {
475             None
476         }
477     }
478 }
479
480 impl dyn Error + 'static + Send {
481     /// Forwards to the method defined on the type `Any`.
482     #[stable(feature = "error_downcast", since = "1.3.0")]
483     #[inline]
484     pub fn is<T: Error + 'static>(&self) -> bool {
485         <dyn Error + 'static>::is::<T>(self)
486     }
487
488     /// Forwards to the method defined on the type `Any`.
489     #[stable(feature = "error_downcast", since = "1.3.0")]
490     #[inline]
491     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
492         <dyn Error + 'static>::downcast_ref::<T>(self)
493     }
494
495     /// Forwards to the method defined on the type `Any`.
496     #[stable(feature = "error_downcast", since = "1.3.0")]
497     #[inline]
498     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
499         <dyn Error + 'static>::downcast_mut::<T>(self)
500     }
501 }
502
503 impl dyn Error + 'static + Send + Sync {
504     /// Forwards to the method defined on the type `Any`.
505     #[stable(feature = "error_downcast", since = "1.3.0")]
506     #[inline]
507     pub fn is<T: Error + 'static>(&self) -> bool {
508         <dyn Error + 'static>::is::<T>(self)
509     }
510
511     /// Forwards to the method defined on the type `Any`.
512     #[stable(feature = "error_downcast", since = "1.3.0")]
513     #[inline]
514     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
515         <dyn Error + 'static>::downcast_ref::<T>(self)
516     }
517
518     /// Forwards to the method defined on the type `Any`.
519     #[stable(feature = "error_downcast", since = "1.3.0")]
520     #[inline]
521     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
522         <dyn Error + 'static>::downcast_mut::<T>(self)
523     }
524 }
525
526 impl dyn Error {
527     #[inline]
528     #[stable(feature = "error_downcast", since = "1.3.0")]
529     /// Attempt to downcast the box to a concrete type.
530     pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
531         if self.is::<T>() {
532             unsafe {
533                 let raw: *mut dyn Error = Box::into_raw(self);
534                 Ok(Box::from_raw(raw as *mut T))
535             }
536         } else {
537             Err(self)
538         }
539     }
540 }
541
542 impl dyn Error + Send {
543     #[inline]
544     #[stable(feature = "error_downcast", since = "1.3.0")]
545     /// Attempt to downcast the box to a concrete type.
546     pub fn downcast<T: Error + 'static>(self: Box<Self>)
547                                         -> Result<Box<T>, Box<dyn Error + Send>> {
548         let err: Box<dyn Error> = self;
549         <dyn Error>::downcast(err).map_err(|s| unsafe {
550             // reapply the Send marker
551             transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
552         })
553     }
554 }
555
556 impl dyn Error + Send + Sync {
557     #[inline]
558     #[stable(feature = "error_downcast", since = "1.3.0")]
559     /// Attempt to downcast the box to a concrete type.
560     pub fn downcast<T: Error + 'static>(self: Box<Self>)
561                                         -> Result<Box<T>, Box<Self>> {
562         let err: Box<dyn Error> = self;
563         <dyn Error>::downcast(err).map_err(|s| unsafe {
564             // reapply the Send+Sync marker
565             transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
566         })
567     }
568 }
569
570 #[cfg(test)]
571 mod tests {
572     use super::Error;
573     use fmt;
574
575     #[derive(Debug, PartialEq)]
576     struct A;
577     #[derive(Debug, PartialEq)]
578     struct B;
579
580     impl fmt::Display for A {
581         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
582             write!(f, "A")
583         }
584     }
585     impl fmt::Display for B {
586         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
587             write!(f, "B")
588         }
589     }
590
591     impl Error for A {
592         fn description(&self) -> &str { "A-desc" }
593     }
594     impl Error for B {
595         fn description(&self) -> &str { "A-desc" }
596     }
597
598     #[test]
599     fn downcasting() {
600         let mut a = A;
601         let a = &mut a as &mut (dyn Error + 'static);
602         assert_eq!(a.downcast_ref::<A>(), Some(&A));
603         assert_eq!(a.downcast_ref::<B>(), None);
604         assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
605         assert_eq!(a.downcast_mut::<B>(), None);
606
607         let a: Box<dyn Error> = Box::new(A);
608         match a.downcast::<B>() {
609             Ok(..) => panic!("expected error"),
610             Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
611         }
612     }
613 }