]> git.lizzy.rs Git - rust.git/blob - src/libstd/error.rs
4b340f70fbc745089b811af196960db05ab274d1
[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 //! # The `Error` trait
14 //!
15 //! `Error` is a trait representing the basic expectations for error values,
16 //! i.e. values of type `E` in [`Result<T, E>`]. At a minimum, errors must provide
17 //! a description, but they may optionally provide additional detail (via
18 //! [`Display`]) and cause chain information:
19 //!
20 //! ```
21 //! use std::fmt::Display;
22 //!
23 //! trait Error: Display {
24 //!     fn description(&self) -> &str;
25 //!
26 //!     fn cause(&self) -> Option<&Error> { None }
27 //! }
28 //! ```
29 //!
30 //! The [`cause`] method is generally used when errors cross "abstraction
31 //! boundaries", i.e.  when a one module must report an error that is "caused"
32 //! by an error from a lower-level module. This setup makes it possible for the
33 //! high-level module to provide its own errors that do not commit to any
34 //! particular implementation, but also reveal some of its implementation for
35 //! debugging via [`cause`] chains.
36 //!
37 //! [`Result<T, E>`]: ../result/enum.Result.html
38 //! [`Display`]: ../fmt/trait.Display.html
39 //! [`cause`]: trait.Error.html#method.cause
40
41 #![stable(feature = "rust1", since = "1.0.0")]
42
43 // A note about crates and the facade:
44 //
45 // Originally, the `Error` trait was defined in libcore, and the impls
46 // were scattered about. However, coherence objected to this
47 // arrangement, because to create the blanket impls for `Box` required
48 // knowing that `&str: !Error`, and we have no means to deal with that
49 // sort of conflict just now. Therefore, for the time being, we have
50 // moved the `Error` trait into libstd. As we evolve a sol'n to the
51 // coherence challenge (e.g., specialization, neg impls, etc) we can
52 // reconsider what crate these items belong in.
53
54 use alloc::allocator;
55 use any::TypeId;
56 use cell;
57 use char;
58 use fmt::{self, Debug, Display};
59 use mem::transmute;
60 use num;
61 use str;
62 use string;
63
64 /// Base functionality for all errors in Rust.
65 #[stable(feature = "rust1", since = "1.0.0")]
66 pub trait Error: Debug + Display {
67     /// A short description of the error.
68     ///
69     /// The description should only be used for a simple message.
70     /// It should not contain newlines or sentence-ending punctuation,
71     /// to facilitate embedding in larger user-facing strings.
72     /// For showing formatted error messages with more information see
73     /// [`Display`].
74     ///
75     /// [`Display`]: ../fmt/trait.Display.html
76     ///
77     /// # Examples
78     ///
79     /// ```
80     /// use std::error::Error;
81     ///
82     /// match "xc".parse::<u32>() {
83     ///     Err(e) => {
84     ///         println!("Error: {}", e.description());
85     ///     }
86     ///     _ => println!("No error"),
87     /// }
88     /// ```
89     #[stable(feature = "rust1", since = "1.0.0")]
90     fn description(&self) -> &str;
91
92     /// The lower-level cause of this error, if any.
93     ///
94     /// # Examples
95     ///
96     /// ```
97     /// use std::error::Error;
98     /// use std::fmt;
99     ///
100     /// #[derive(Debug)]
101     /// struct SuperError {
102     ///     side: SuperErrorSideKick,
103     /// }
104     ///
105     /// impl fmt::Display for SuperError {
106     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107     ///         write!(f, "SuperError is here!")
108     ///     }
109     /// }
110     ///
111     /// impl Error for SuperError {
112     ///     fn description(&self) -> &str {
113     ///         "I'm the superhero of errors"
114     ///     }
115     ///
116     ///     fn cause(&self) -> Option<&Error> {
117     ///         Some(&self.side)
118     ///     }
119     /// }
120     ///
121     /// #[derive(Debug)]
122     /// struct SuperErrorSideKick;
123     ///
124     /// impl fmt::Display for SuperErrorSideKick {
125     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126     ///         write!(f, "SuperErrorSideKick is here!")
127     ///     }
128     /// }
129     ///
130     /// impl Error for SuperErrorSideKick {
131     ///     fn description(&self) -> &str {
132     ///         "I'm SuperError side kick"
133     ///     }
134     /// }
135     ///
136     /// fn get_super_error() -> Result<(), SuperError> {
137     ///     Err(SuperError { side: SuperErrorSideKick })
138     /// }
139     ///
140     /// fn main() {
141     ///     match get_super_error() {
142     ///         Err(e) => {
143     ///             println!("Error: {}", e.description());
144     ///             println!("Caused by: {}", e.cause().unwrap());
145     ///         }
146     ///         _ => println!("No error"),
147     ///     }
148     /// }
149     /// ```
150     #[stable(feature = "rust1", since = "1.0.0")]
151     fn cause(&self) -> Option<&Error> { None }
152
153     /// Get the `TypeId` of `self`
154     #[doc(hidden)]
155     #[unstable(feature = "error_type_id",
156                reason = "unclear whether to commit to this public implementation detail",
157                issue = "27745")]
158     fn type_id(&self) -> TypeId where Self: 'static {
159         TypeId::of::<Self>()
160     }
161 }
162
163 #[stable(feature = "rust1", since = "1.0.0")]
164 impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
165     fn from(err: E) -> Box<Error + 'a> {
166         Box::new(err)
167     }
168 }
169
170 #[stable(feature = "rust1", since = "1.0.0")]
171 impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<Error + Send + Sync + 'a> {
172     fn from(err: E) -> Box<Error + Send + Sync + 'a> {
173         Box::new(err)
174     }
175 }
176
177 #[stable(feature = "rust1", since = "1.0.0")]
178 impl From<String> for Box<Error + Send + Sync> {
179     fn from(err: String) -> Box<Error + Send + Sync> {
180         #[derive(Debug)]
181         struct StringError(String);
182
183         impl Error for StringError {
184             fn description(&self) -> &str { &self.0 }
185         }
186
187         impl Display for StringError {
188             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
189                 Display::fmt(&self.0, f)
190             }
191         }
192
193         Box::new(StringError(err))
194     }
195 }
196
197 #[stable(feature = "string_box_error", since = "1.6.0")]
198 impl From<String> for Box<Error> {
199     fn from(str_err: String) -> Box<Error> {
200         let err1: Box<Error + Send + Sync> = From::from(str_err);
201         let err2: Box<Error> = err1;
202         err2
203     }
204 }
205
206 #[stable(feature = "rust1", since = "1.0.0")]
207 impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> {
208     fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> {
209         From::from(String::from(err))
210     }
211 }
212
213 #[stable(feature = "string_box_error", since = "1.6.0")]
214 impl<'a> From<&'a str> for Box<Error> {
215     fn from(err: &'a str) -> Box<Error> {
216         From::from(String::from(err))
217     }
218 }
219
220 #[unstable(feature = "never_type_impls", issue = "35121")]
221 impl Error for ! {
222     fn description(&self) -> &str { *self }
223 }
224
225 #[unstable(feature = "allocator_api",
226            reason = "the precise API and guarantees it provides may be tweaked.",
227            issue = "27700")]
228 impl Error for allocator::AllocErr {
229     fn description(&self) -> &str {
230         allocator::AllocErr::description(self)
231     }
232 }
233
234 #[unstable(feature = "allocator_api",
235            reason = "the precise API and guarantees it provides may be tweaked.",
236            issue = "27700")]
237 impl Error for allocator::CannotReallocInPlace {
238     fn description(&self) -> &str {
239         allocator::CannotReallocInPlace::description(self)
240     }
241 }
242
243 #[stable(feature = "rust1", since = "1.0.0")]
244 impl Error for str::ParseBoolError {
245     fn description(&self) -> &str { "failed to parse bool" }
246 }
247
248 #[stable(feature = "rust1", since = "1.0.0")]
249 impl Error for str::Utf8Error {
250     fn description(&self) -> &str {
251         "invalid utf-8: corrupt contents"
252     }
253 }
254
255 #[stable(feature = "rust1", since = "1.0.0")]
256 impl Error for num::ParseIntError {
257     fn description(&self) -> &str {
258         self.__description()
259     }
260 }
261
262 #[unstable(feature = "try_from", issue = "33417")]
263 impl Error for num::TryFromIntError {
264     fn description(&self) -> &str {
265         self.__description()
266     }
267 }
268
269 #[stable(feature = "rust1", since = "1.0.0")]
270 impl Error for num::ParseFloatError {
271     fn description(&self) -> &str {
272         self.__description()
273     }
274 }
275
276 #[stable(feature = "rust1", since = "1.0.0")]
277 impl Error for string::FromUtf8Error {
278     fn description(&self) -> &str {
279         "invalid utf-8"
280     }
281 }
282
283 #[stable(feature = "rust1", since = "1.0.0")]
284 impl Error for string::FromUtf16Error {
285     fn description(&self) -> &str {
286         "invalid utf-16"
287     }
288 }
289
290 #[stable(feature = "str_parse_error2", since = "1.8.0")]
291 impl Error for string::ParseError {
292     fn description(&self) -> &str {
293         match *self {}
294     }
295 }
296
297 #[stable(feature = "decode_utf16", since = "1.9.0")]
298 impl Error for char::DecodeUtf16Error {
299     fn description(&self) -> &str {
300         "unpaired surrogate found"
301     }
302 }
303
304 #[stable(feature = "box_error", since = "1.8.0")]
305 impl<T: Error> Error for Box<T> {
306     fn description(&self) -> &str {
307         Error::description(&**self)
308     }
309
310     fn cause(&self) -> Option<&Error> {
311         Error::cause(&**self)
312     }
313 }
314
315 #[stable(feature = "fmt_error", since = "1.11.0")]
316 impl Error for fmt::Error {
317     fn description(&self) -> &str {
318         "an error occurred when formatting an argument"
319     }
320 }
321
322 #[stable(feature = "try_borrow", since = "1.13.0")]
323 impl Error for cell::BorrowError {
324     fn description(&self) -> &str {
325         "already mutably borrowed"
326     }
327 }
328
329 #[stable(feature = "try_borrow", since = "1.13.0")]
330 impl Error for cell::BorrowMutError {
331     fn description(&self) -> &str {
332         "already borrowed"
333     }
334 }
335
336 #[unstable(feature = "try_from", issue = "33417")]
337 impl Error for char::CharTryFromError {
338     fn description(&self) -> &str {
339         "converted integer out of range for `char`"
340     }
341 }
342
343 #[stable(feature = "char_from_str", since = "1.19.0")]
344 impl Error for char::ParseCharError {
345     fn description(&self) -> &str {
346         self.__description()
347     }
348 }
349
350
351 // copied from any.rs
352 impl Error + 'static {
353     /// Returns true if the boxed type is the same as `T`
354     #[stable(feature = "error_downcast", since = "1.3.0")]
355     #[inline]
356     pub fn is<T: Error + 'static>(&self) -> bool {
357         // Get TypeId of the type this function is instantiated with
358         let t = TypeId::of::<T>();
359
360         // Get TypeId of the type in the trait object
361         let boxed = self.type_id();
362
363         // Compare both TypeIds on equality
364         t == boxed
365     }
366
367     /// Returns some reference to the boxed value if it is of type `T`, or
368     /// `None` if it isn't.
369     #[stable(feature = "error_downcast", since = "1.3.0")]
370     #[inline]
371     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
372         if self.is::<T>() {
373             unsafe {
374                 Some(&*(self as *const Error as *const T))
375             }
376         } else {
377             None
378         }
379     }
380
381     /// Returns some mutable reference to the boxed value if it is of type `T`, or
382     /// `None` if it isn't.
383     #[stable(feature = "error_downcast", since = "1.3.0")]
384     #[inline]
385     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
386         if self.is::<T>() {
387             unsafe {
388                 Some(&mut *(self as *mut Error as *mut T))
389             }
390         } else {
391             None
392         }
393     }
394 }
395
396 impl Error + 'static + Send {
397     /// Forwards to the method defined on the type `Any`.
398     #[stable(feature = "error_downcast", since = "1.3.0")]
399     #[inline]
400     pub fn is<T: Error + 'static>(&self) -> bool {
401         <Error + 'static>::is::<T>(self)
402     }
403
404     /// Forwards to the method defined on the type `Any`.
405     #[stable(feature = "error_downcast", since = "1.3.0")]
406     #[inline]
407     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
408         <Error + 'static>::downcast_ref::<T>(self)
409     }
410
411     /// Forwards to the method defined on the type `Any`.
412     #[stable(feature = "error_downcast", since = "1.3.0")]
413     #[inline]
414     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
415         <Error + 'static>::downcast_mut::<T>(self)
416     }
417 }
418
419 impl Error + 'static + Send + Sync {
420     /// Forwards to the method defined on the type `Any`.
421     #[stable(feature = "error_downcast", since = "1.3.0")]
422     #[inline]
423     pub fn is<T: Error + 'static>(&self) -> bool {
424         <Error + 'static>::is::<T>(self)
425     }
426
427     /// Forwards to the method defined on the type `Any`.
428     #[stable(feature = "error_downcast", since = "1.3.0")]
429     #[inline]
430     pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
431         <Error + 'static>::downcast_ref::<T>(self)
432     }
433
434     /// Forwards to the method defined on the type `Any`.
435     #[stable(feature = "error_downcast", since = "1.3.0")]
436     #[inline]
437     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
438         <Error + 'static>::downcast_mut::<T>(self)
439     }
440 }
441
442 impl Error {
443     #[inline]
444     #[stable(feature = "error_downcast", since = "1.3.0")]
445     /// Attempt to downcast the box to a concrete type.
446     pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> {
447         if self.is::<T>() {
448             unsafe {
449                 let raw: *mut Error = Box::into_raw(self);
450                 Ok(Box::from_raw(raw as *mut T))
451             }
452         } else {
453             Err(self)
454         }
455     }
456 }
457
458 impl Error + Send {
459     #[inline]
460     #[stable(feature = "error_downcast", since = "1.3.0")]
461     /// Attempt to downcast the box to a concrete type.
462     pub fn downcast<T: Error + 'static>(self: Box<Self>)
463                                         -> Result<Box<T>, Box<Error + Send>> {
464         let err: Box<Error> = self;
465         <Error>::downcast(err).map_err(|s| unsafe {
466             // reapply the Send marker
467             transmute::<Box<Error>, Box<Error + Send>>(s)
468         })
469     }
470 }
471
472 impl Error + Send + Sync {
473     #[inline]
474     #[stable(feature = "error_downcast", since = "1.3.0")]
475     /// Attempt to downcast the box to a concrete type.
476     pub fn downcast<T: Error + 'static>(self: Box<Self>)
477                                         -> Result<Box<T>, Box<Self>> {
478         let err: Box<Error> = self;
479         <Error>::downcast(err).map_err(|s| unsafe {
480             // reapply the Send+Sync marker
481             transmute::<Box<Error>, Box<Error + Send + Sync>>(s)
482         })
483     }
484 }
485
486 #[cfg(test)]
487 mod tests {
488     use super::Error;
489     use fmt;
490
491     #[derive(Debug, PartialEq)]
492     struct A;
493     #[derive(Debug, PartialEq)]
494     struct B;
495
496     impl fmt::Display for A {
497         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
498             write!(f, "A")
499         }
500     }
501     impl fmt::Display for B {
502         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
503             write!(f, "B")
504         }
505     }
506
507     impl Error for A {
508         fn description(&self) -> &str { "A-desc" }
509     }
510     impl Error for B {
511         fn description(&self) -> &str { "A-desc" }
512     }
513
514     #[test]
515     fn downcasting() {
516         let mut a = A;
517         let mut a = &mut a as &mut (Error + 'static);
518         assert_eq!(a.downcast_ref::<A>(), Some(&A));
519         assert_eq!(a.downcast_ref::<B>(), None);
520         assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
521         assert_eq!(a.downcast_mut::<B>(), None);
522
523         let a: Box<Error> = Box::new(A);
524         match a.downcast::<B>() {
525             Ok(..) => panic!("expected error"),
526             Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
527         }
528     }
529 }