core2/
error.rs

1//! Traits for working with Errors.
2
3// A note about crates and the facade:
4//
5// Originally, the `Error` trait was defined in libcore, and the impls
6// were scattered about. However, coherence objected to this
7// arrangement, because to create the blanket impls for `Box` required
8// knowing that `&str: !Error`, and we have no means to deal with that
9// sort of conflict just now. Therefore, for the time being, we have
10// moved the `Error` trait into libstd. As we evolve a sol'n to the
11// coherence challenge (e.g., specialization, neg impls, etc) we can
12// reconsider what crate these items belong in.
13
14#[allow(deprecated)]
15use core::alloc::LayoutErr;
16
17use core::any::TypeId;
18use core::fmt::{Debug, Display};
19
20#[cfg(feature = "alloc")]
21use alloc::{string::String, borrow::Cow, boxed::Box};
22
23/// `Error` is a trait representing the basic expectations for error values,
24/// i.e., values of type `E` in [`Result<T, E>`]. Errors must describe
25/// themselves through the [`Display`] and [`Debug`] traits, and may provide
26/// cause chain information:
27///
28/// [`Error::source()`] is generally used when errors cross
29/// "abstraction boundaries". If one module must report an error that is caused
30/// by an error from a lower-level module, it can allow accessing that error
31/// via [`Error::source()`]. This makes it possible for the high-level
32/// module to provide its own errors while also revealing some of the
33/// implementation for debugging via `source` chains.
34///
35/// [`Result<T, E>`]: Result
36pub trait Error: Debug + Display {
37    /// The lower-level source of this error, if any.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use std::error::Error;
43    /// use std::fmt;
44    ///
45    /// #[derive(Debug)]
46    /// struct SuperError {
47    ///     side: SuperErrorSideKick,
48    /// }
49    ///
50    /// impl fmt::Display for SuperError {
51    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52    ///         write!(f, "SuperError is here!")
53    ///     }
54    /// }
55    ///
56    /// impl Error for SuperError {
57    ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
58    ///         Some(&self.side)
59    ///     }
60    /// }
61    ///
62    /// #[derive(Debug)]
63    /// struct SuperErrorSideKick;
64    ///
65    /// impl fmt::Display for SuperErrorSideKick {
66    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67    ///         write!(f, "SuperErrorSideKick is here!")
68    ///     }
69    /// }
70    ///
71    /// impl Error for SuperErrorSideKick {}
72    ///
73    /// fn get_super_error() -> Result<(), SuperError> {
74    ///     Err(SuperError { side: SuperErrorSideKick })
75    /// }
76    ///
77    /// fn main() {
78    ///     match get_super_error() {
79    ///         Err(e) => {
80    ///             println!("Error: {}", e);
81    ///             println!("Caused by: {}", e.source().unwrap());
82    ///         }
83    ///         _ => println!("No error"),
84    ///     }
85    /// }
86    /// ```
87    fn source(&self) -> Option<&(dyn Error + 'static)> {
88        None
89    }
90
91    /// Gets the `TypeId` of `self`.
92    #[doc(hidden)]
93    fn type_id(&self, _: private::Internal) -> TypeId
94    where
95        Self: 'static,
96    {
97        TypeId::of::<Self>()
98    }
99}
100
101mod private {
102    // This is a hack to prevent `type_id` from being overridden by `Error`
103    // implementations, since that can enable unsound downcasting.
104    #[derive(Debug)]
105    pub struct Internal;
106}
107
108#[cfg(feature = "alloc")]
109impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
110    /// Converts a type of [`Error`] into a box of dyn [`Error`].
111    ///
112    /// # Examples
113    ///
114    /// ```
115    /// use std::error::Error;
116    /// use std::fmt;
117    /// use std::mem;
118    ///
119    /// #[derive(Debug)]
120    /// struct AnError;
121    ///
122    /// impl fmt::Display for AnError {
123    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124    ///         write!(f , "An error")
125    ///     }
126    /// }
127    ///
128    /// impl Error for AnError {}
129    ///
130    /// let an_error = AnError;
131    /// assert!(0 == mem::size_of_val(&an_error));
132    /// let a_boxed_error = Box::<dyn Error>::from(an_error);
133    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
134    /// ```
135    fn from(err: E) -> Box<dyn Error + 'a> {
136        Box::new(err)
137    }
138}
139
140#[cfg(feature = "alloc")]
141impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
142    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
143    /// dyn [`Error`] + [`Send`] + [`Sync`].
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// use std::error::Error;
149    /// use std::fmt;
150    /// use std::mem;
151    ///
152    /// #[derive(Debug)]
153    /// struct AnError;
154    ///
155    /// impl fmt::Display for AnError {
156    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157    ///         write!(f , "An error")
158    ///     }
159    /// }
160    ///
161    /// impl Error for AnError {}
162    ///
163    /// unsafe impl Send for AnError {}
164    ///
165    /// unsafe impl Sync for AnError {}
166    ///
167    /// let an_error = AnError;
168    /// assert!(0 == mem::size_of_val(&an_error));
169    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
170    /// assert!(
171    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
172    /// ```
173    fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
174        Box::new(err)
175    }
176}
177
178#[cfg(feature = "alloc")]
179impl From<String> for Box<dyn Error + Send + Sync> {
180    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
181    ///
182    /// # Examples
183    ///
184    /// ```
185    /// use std::error::Error;
186    /// use std::mem;
187    ///
188    /// let a_string_error = "a string error".to_string();
189    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
190    /// assert!(
191    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
192    /// ```
193    #[inline]
194    fn from(err: String) -> Box<dyn Error + Send + Sync> {
195        struct StringError(String);
196
197        impl Error for StringError {}
198
199        impl Display for StringError {
200            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
201                Display::fmt(&self.0, f)
202            }
203        }
204
205        // Purposefully skip printing "StringError(..)"
206        impl Debug for StringError {
207            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
208                Debug::fmt(&self.0, f)
209            }
210        }
211
212        Box::new(StringError(err))
213    }
214}
215
216#[cfg(feature = "alloc")]
217impl From<String> for Box<dyn Error> {
218    /// Converts a [`String`] into a box of dyn [`Error`].
219    ///
220    /// # Examples
221    ///
222    /// ```
223    /// use std::error::Error;
224    /// use std::mem;
225    ///
226    /// let a_string_error = "a string error".to_string();
227    /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
228    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
229    /// ```
230    fn from(str_err: String) -> Box<dyn Error> {
231        let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
232        let err2: Box<dyn Error> = err1;
233        err2
234    }
235}
236
237#[cfg(feature = "alloc")]
238impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
239    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
240    ///
241    /// [`str`]: prim@str
242    ///
243    /// # Examples
244    ///
245    /// ```
246    /// use std::error::Error;
247    /// use std::mem;
248    ///
249    /// let a_str_error = "a str error";
250    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
251    /// assert!(
252    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
253    /// ```
254    #[inline]
255    fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
256        From::from(String::from(err))
257    }
258}
259
260#[cfg(feature = "alloc")]
261impl From<&str> for Box<dyn Error> {
262    /// Converts a [`str`] into a box of dyn [`Error`].
263    ///
264    /// [`str`]: prim@str
265    ///
266    /// # Examples
267    ///
268    /// ```
269    /// use std::error::Error;
270    /// use std::mem;
271    ///
272    /// let a_str_error = "a str error";
273    /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
274    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
275    /// ```
276    fn from(err: &str) -> Box<dyn Error> {
277        From::from(String::from(err))
278    }
279}
280
281#[cfg(feature = "alloc")]
282impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
283    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// use std::error::Error;
289    /// use std::mem;
290    /// use std::borrow::Cow;
291    ///
292    /// let a_cow_str_error = Cow::from("a str error");
293    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
294    /// assert!(
295    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
296    /// ```
297    fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
298        From::from(String::from(err))
299    }
300}
301
302#[cfg(feature = "alloc")]
303impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
304    /// Converts a [`Cow`] into a box of dyn [`Error`].
305    ///
306    /// # Examples
307    ///
308    /// ```
309    /// use std::error::Error;
310    /// use std::mem;
311    /// use std::borrow::Cow;
312    ///
313    /// let a_cow_str_error = Cow::from("a str error");
314    /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
315    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
316    /// ```
317    fn from(err: Cow<'a, str>) -> Box<dyn Error> {
318        From::from(String::from(err))
319    }
320}
321
322// #[unstable(feature = "never_type", issue = "35121")]
323#[cfg(feature = "nightly")]
324impl Error for ! {}
325
326#[allow(deprecated)]
327impl Error for LayoutErr {}
328
329impl Error for core::str::ParseBoolError {}
330
331impl Error for core::str::Utf8Error {}
332
333impl Error for core::num::ParseIntError {}
334
335impl Error for core::num::TryFromIntError {}
336
337impl Error for core::array::TryFromSliceError {}
338
339impl Error for core::num::ParseFloatError {}
340
341#[cfg(feature = "alloc")]
342impl Error for alloc::string::FromUtf8Error {}
343
344#[cfg(feature = "alloc")]
345impl Error for alloc::string::FromUtf16Error {}
346
347
348#[cfg(feature = "alloc")]
349impl<T: Error> Error for Box<T> {
350    fn source(&self) -> Option<&(dyn Error + 'static)> {
351        Error::source(&**self)
352    }
353}
354
355// Copied from `any.rs`.
356impl dyn Error + 'static {
357    /// Returns `true` if the boxed type is the same as `T`
358    #[inline]
359    pub fn is<T: Error + 'static>(&self) -> bool {
360        // Get `TypeId` of the type this function is instantiated with.
361        let t = TypeId::of::<T>();
362
363        // Get `TypeId` of the type in the trait object.
364        let boxed = self.type_id(private::Internal);
365
366        // Compare both `TypeId`s on equality.
367        t == boxed
368    }
369
370    /// Returns some reference to the boxed value if it is of type `T`, or
371    /// `None` if it isn't.
372    #[inline]
373    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
374        if self.is::<T>() {
375            unsafe { Some(&*(self as *const dyn Error as *const T)) }
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    #[inline]
384    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
385        if self.is::<T>() {
386            unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) }
387        } else {
388            None
389        }
390    }
391}
392
393impl dyn Error + 'static + Send {
394    /// Forwards to the method defined on the type `dyn Error`.
395    #[inline]
396    pub fn is<T: Error + 'static>(&self) -> bool {
397        <dyn Error + 'static>::is::<T>(self)
398    }
399
400    /// Forwards to the method defined on the type `dyn Error`.
401    #[inline]
402    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
403        <dyn Error + 'static>::downcast_ref::<T>(self)
404    }
405
406    /// Forwards to the method defined on the type `dyn Error`.
407    #[inline]
408    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
409        <dyn Error + 'static>::downcast_mut::<T>(self)
410    }
411}
412
413impl dyn Error + 'static + Send + Sync {
414    /// Forwards to the method defined on the type `dyn Error`.
415    #[inline]
416    pub fn is<T: Error + 'static>(&self) -> bool {
417        <dyn Error + 'static>::is::<T>(self)
418    }
419
420    /// Forwards to the method defined on the type `dyn Error`.
421    #[inline]
422    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
423        <dyn Error + 'static>::downcast_ref::<T>(self)
424    }
425
426    /// Forwards to the method defined on the type `dyn Error`.
427    #[inline]
428    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
429        <dyn Error + 'static>::downcast_mut::<T>(self)
430    }
431}
432
433#[cfg(feature = "alloc")]
434impl dyn Error {
435    #[inline]
436    /// Attempts to downcast the box to a concrete type.
437    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
438        if self.is::<T>() {
439            unsafe {
440                let raw: *mut dyn Error = Box::into_raw(self);
441                Ok(Box::from_raw(raw as *mut T))
442            }
443        } else {
444            Err(self)
445        }
446    }
447}
448
449#[cfg(feature = "alloc")]
450impl dyn Error + Send {
451    #[inline]
452    /// Attempts to downcast the box to a concrete type.
453    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
454        let err: Box<dyn Error> = self;
455        <dyn Error>::downcast(err).map_err(|s| unsafe {
456            // Reapply the `Send` marker.
457            core::mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
458        })
459    }
460}
461
462#[cfg(feature = "alloc")]
463impl dyn Error + Send + Sync {
464    #[inline]
465    /// Attempts to downcast the box to a concrete type.
466    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
467        let err: Box<dyn Error> = self;
468        <dyn Error>::downcast(err).map_err(|s| unsafe {
469            // Reapply the `Send + Sync` marker.
470            core::mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
471        })
472    }
473}