//! Traits for working with Errors. #![stable(feature = "rust1", since = "1.0.0")] // A note about crates and the facade: // // Originally, the `Error` trait was defined in libcore, and the impls // were scattered about. However, coherence objected to this // arrangement, because to create the blanket impls for `Box` required // knowing that `&str: !Error`, and we have no means to deal with that // sort of conflict just now. Therefore, for the time being, we have // moved the `Error` trait into libstd. As we evolve a sol'n to the // coherence challenge (e.g., specialization, neg impls, etc) we can // reconsider what crate these items belong in. use core::array; use crate::alloc::{AllocErr, LayoutErr, CannotReallocInPlace}; use crate::any::TypeId; use crate::borrow::Cow; use crate::cell; use crate::char; use crate::fmt::{self, Debug, Display}; use crate::mem::transmute; use crate::num; use crate::str; use crate::string; /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result`]. Errors must describe /// themselves through the [`Display`] and [`Debug`] traits, and may provide /// cause chain information: /// /// The [`source`] method is generally used when errors cross "abstraction /// boundaries". If one module must report an error that is caused by an error /// from a lower-level module, it can allow access to that error via the /// [`source`] method. This makes it possible for the high-level module to /// provide its own errors while also revealing some of the implementation for /// debugging via [`source`] chains. /// /// [`Result`]: ../result/enum.Result.html /// [`Display`]: ../fmt/trait.Display.html /// [`Debug`]: ../fmt/trait.Debug.html /// [`source`]: trait.Error.html#method.source #[stable(feature = "rust1", since = "1.0.0")] pub trait Error: Debug + Display { /// **This method is soft-deprecated.** /// /// Although using it won’t cause compilation warning, /// new code should use [`Display`] instead /// and new `impl`s can omit it. /// /// To obtain error description as a string, use `to_string()`. /// /// [`Display`]: ../fmt/trait.Display.html /// /// # Examples /// /// ``` /// match "xc".parse::() { /// Err(e) => { /// // Print `e` itself, not `e.description()`. /// println!("Error: {}", e); /// } /// _ => println!("No error"), /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn description(&self) -> &str { "description() is deprecated; use Display" } /// The lower-level cause of this error, if any. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::fmt; /// /// #[derive(Debug)] /// struct SuperError { /// side: SuperErrorSideKick, /// } /// /// impl fmt::Display for SuperError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "SuperError is here!") /// } /// } /// /// impl Error for SuperError { /// fn description(&self) -> &str { /// "I'm the superhero of errors" /// } /// /// fn cause(&self) -> Option<&dyn Error> { /// Some(&self.side) /// } /// } /// /// #[derive(Debug)] /// struct SuperErrorSideKick; /// /// impl fmt::Display for SuperErrorSideKick { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "SuperErrorSideKick is here!") /// } /// } /// /// impl Error for SuperErrorSideKick { /// fn description(&self) -> &str { /// "I'm SuperError side kick" /// } /// } /// /// fn get_super_error() -> Result<(), SuperError> { /// Err(SuperError { side: SuperErrorSideKick }) /// } /// /// fn main() { /// match get_super_error() { /// Err(e) => { /// println!("Error: {}", e.description()); /// println!("Caused by: {}", e.cause().unwrap()); /// } /// _ => println!("No error"), /// } /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.33.0", reason = "replaced by Error::source, which can support \ downcasting")] fn cause(&self) -> Option<&dyn Error> { self.source() } /// The lower-level source of this error, if any. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::fmt; /// /// #[derive(Debug)] /// struct SuperError { /// side: SuperErrorSideKick, /// } /// /// impl fmt::Display for SuperError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "SuperError is here!") /// } /// } /// /// impl Error for SuperError { /// fn description(&self) -> &str { /// "I'm the superhero of errors" /// } /// /// fn source(&self) -> Option<&(dyn Error + 'static)> { /// Some(&self.side) /// } /// } /// /// #[derive(Debug)] /// struct SuperErrorSideKick; /// /// impl fmt::Display for SuperErrorSideKick { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "SuperErrorSideKick is here!") /// } /// } /// /// impl Error for SuperErrorSideKick { /// fn description(&self) -> &str { /// "I'm SuperError side kick" /// } /// } /// /// fn get_super_error() -> Result<(), SuperError> { /// Err(SuperError { side: SuperErrorSideKick }) /// } /// /// fn main() { /// match get_super_error() { /// Err(e) => { /// println!("Error: {}", e.description()); /// println!("Caused by: {}", e.source().unwrap()); /// } /// _ => println!("No error"), /// } /// } /// ``` #[stable(feature = "error_source", since = "1.30.0")] fn source(&self) -> Option<&(dyn Error + 'static)> { None } /// Gets the `TypeId` of `self` #[doc(hidden)] #[unstable(feature = "error_type_id", reason = "this is memory unsafe to override in user code", issue = "60784")] fn type_id(&self, _: private::Internal) -> TypeId where Self: 'static { TypeId::of::() } } mod private { // This is a hack to prevent `type_id` from being overridden by `Error` // implementations, since that can enable unsound downcasting. #[unstable(feature = "error_type_id", issue = "60784")] #[derive(Debug)] pub struct Internal; } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + 'a> From for Box { /// Converts a type of [`Error`] into a box of dyn [`Error`]. /// /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::fmt; /// use std::mem; /// /// #[derive(Debug)] /// struct AnError; /// /// impl fmt::Display for AnError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f , "An error") /// } /// } /// /// impl Error for AnError { /// fn description(&self) -> &str { /// "Description of an error" /// } /// } /// /// let an_error = AnError; /// assert!(0 == mem::size_of_val(&an_error)); /// let a_boxed_error = Box::::from(an_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: E) -> Box { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] + /// [`Send`] + [`Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::fmt; /// use std::mem; /// /// #[derive(Debug)] /// struct AnError; /// /// impl fmt::Display for AnError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f , "An error") /// } /// } /// /// impl Error for AnError { /// fn description(&self) -> &str { /// "Description of an error" /// } /// } /// /// unsafe impl Send for AnError {} /// /// unsafe impl Sync for AnError {} /// /// let an_error = AnError; /// assert!(0 == mem::size_of_val(&an_error)); /// let a_boxed_error = Box::::from(an_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: E) -> Box { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_string_error = "a string error".to_string(); /// let a_boxed_error = Box::::from(a_string_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: String) -> Box { struct StringError(String); impl Error for StringError { fn description(&self) -> &str { &self.0 } } impl Display for StringError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(&self.0, f) } } // Purposefully skip printing "StringError(..)" impl Debug for StringError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Debug::fmt(&self.0, f) } } Box::new(StringError(err)) } } #[stable(feature = "string_box_error", since = "1.6.0")] impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. /// /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_string_error = "a string error".to_string(); /// let a_boxed_error = Box::::from(a_string_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); let err2: Box = err1; err2 } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_str_error = "a str error"; /// let a_boxed_error = Box::::from(a_str_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: &str) -> Box { From::from(String::from(err)) } } #[stable(feature = "string_box_error", since = "1.6.0")] impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_str_error = "a str error"; /// let a_boxed_error = Box::::from(a_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: &str) -> Box { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// use std::borrow::Cow; /// /// let a_cow_str_error = Cow::from("a str error"); /// let a_boxed_error = Box::::from(a_cow_str_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Error`]: ../error/trait.Error.html /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// use std::borrow::Cow; /// /// let a_cow_str_error = Cow::from("a str error"); /// let a_boxed_error = Box::::from(a_cow_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) } } #[unstable(feature = "never_type", issue = "35121")] impl Error for ! { fn description(&self) -> &str { *self } } #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] impl Error for AllocErr { fn description(&self) -> &str { "memory allocation failed" } } #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] impl Error for LayoutErr { fn description(&self) -> &str { "invalid parameters to Layout::from_size_align" } } #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] impl Error for CannotReallocInPlace { fn description(&self) -> &str { CannotReallocInPlace::description(self) } } #[stable(feature = "rust1", since = "1.0.0")] impl Error for str::ParseBoolError { fn description(&self) -> &str { "failed to parse bool" } } #[stable(feature = "rust1", since = "1.0.0")] impl Error for str::Utf8Error { fn description(&self) -> &str { "invalid utf-8: corrupt contents" } } #[stable(feature = "rust1", since = "1.0.0")] impl Error for num::ParseIntError { fn description(&self) -> &str { self.__description() } } #[stable(feature = "try_from", since = "1.34.0")] impl Error for num::TryFromIntError { fn description(&self) -> &str { self.__description() } } #[stable(feature = "try_from", since = "1.34.0")] impl Error for array::TryFromSliceError { fn description(&self) -> &str { self.__description() } } #[stable(feature = "rust1", since = "1.0.0")] impl Error for num::ParseFloatError { fn description(&self) -> &str { self.__description() } } #[stable(feature = "rust1", since = "1.0.0")] impl Error for string::FromUtf8Error { fn description(&self) -> &str { "invalid utf-8" } } #[stable(feature = "rust1", since = "1.0.0")] impl Error for string::FromUtf16Error { fn description(&self) -> &str { "invalid utf-16" } } #[stable(feature = "str_parse_error2", since = "1.8.0")] impl Error for string::ParseError { fn description(&self) -> &str { match *self {} } } #[stable(feature = "decode_utf16", since = "1.9.0")] impl Error for char::DecodeUtf16Error { fn description(&self) -> &str { "unpaired surrogate found" } } #[stable(feature = "box_error", since = "1.8.0")] impl Error for Box { fn description(&self) -> &str { Error::description(&**self) } #[allow(deprecated)] fn cause(&self) -> Option<&dyn Error> { Error::cause(&**self) } } #[stable(feature = "fmt_error", since = "1.11.0")] impl Error for fmt::Error { fn description(&self) -> &str { "an error occurred when formatting an argument" } } #[stable(feature = "try_borrow", since = "1.13.0")] impl Error for cell::BorrowError { fn description(&self) -> &str { "already mutably borrowed" } } #[stable(feature = "try_borrow", since = "1.13.0")] impl Error for cell::BorrowMutError { fn description(&self) -> &str { "already borrowed" } } #[stable(feature = "try_from", since = "1.34.0")] impl Error for char::CharTryFromError { fn description(&self) -> &str { "converted integer out of range for `char`" } } #[stable(feature = "char_from_str", since = "1.20.0")] impl Error for char::ParseCharError { fn description(&self) -> &str { self.__description() } } // copied from any.rs impl dyn Error + 'static { /// Returns `true` if the boxed type is the same as `T` #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { // Get TypeId of the type this function is instantiated with let t = TypeId::of::(); // Get TypeId of the type in the trait object let boxed = self.type_id(private::Internal); // Compare both TypeIds on equality t == boxed } /// Returns some reference to the boxed value if it is of type `T`, or /// `None` if it isn't. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { Some(&*(self as *const dyn Error as *const T)) } } else { None } } /// Returns some mutable reference to the boxed value if it is of type `T`, or /// `None` if it isn't. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } } else { None } } } impl dyn Error + 'static + Send { /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { ::is::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { ::downcast_ref::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } } impl dyn Error + 'static + Send + Sync { /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn is(&self) -> bool { ::is::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { ::downcast_ref::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } } impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] /// Attempt to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { if self.is::() { unsafe { let raw: *mut dyn Error = Box::into_raw(self); Ok(Box::from_raw(raw as *mut T)) } } else { Err(self) } } /// Returns an iterator starting with the current error and continuing with /// recursively calling [`source`]. /// /// # Examples /// /// ``` /// #![feature(error_iter)] /// use std::error::Error; /// use std::fmt; /// /// #[derive(Debug)] /// struct A; /// /// #[derive(Debug)] /// struct B(Option>); /// /// impl fmt::Display for A { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "A") /// } /// } /// /// impl fmt::Display for B { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "B") /// } /// } /// /// impl Error for A {} /// /// impl Error for B { /// fn source(&self) -> Option<&(dyn Error + 'static)> { /// self.0.as_ref().map(|e| e.as_ref()) /// } /// } /// /// let b = B(Some(Box::new(A))); /// /// // let err : Box = b.into(); // or /// let err = &b as &(dyn Error); /// /// let mut iter = err.iter_chain(); /// /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); /// assert!(iter.next().is_none()); /// assert!(iter.next().is_none()); /// ``` /// /// [`source`]: trait.Error.html#method.source #[unstable(feature = "error_iter", issue = "58520")] #[inline] pub fn iter_chain(&self) -> ErrorIter<'_> { ErrorIter { current: Some(self), } } /// Returns an iterator starting with the [`source`] of this error /// and continuing with recursively calling [`source`]. /// /// # Examples /// /// ``` /// #![feature(error_iter)] /// use std::error::Error; /// use std::fmt; /// /// #[derive(Debug)] /// struct A; /// /// #[derive(Debug)] /// struct B(Option>); /// /// #[derive(Debug)] /// struct C(Option>); /// /// impl fmt::Display for A { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "A") /// } /// } /// /// impl fmt::Display for B { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "B") /// } /// } /// /// impl fmt::Display for C { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "C") /// } /// } /// /// impl Error for A {} /// /// impl Error for B { /// fn source(&self) -> Option<&(dyn Error + 'static)> { /// self.0.as_ref().map(|e| e.as_ref()) /// } /// } /// /// impl Error for C { /// fn source(&self) -> Option<&(dyn Error + 'static)> { /// self.0.as_ref().map(|e| e.as_ref()) /// } /// } /// /// let b = B(Some(Box::new(A))); /// let c = C(Some(Box::new(b))); /// /// // let err : Box = c.into(); // or /// let err = &c as &(dyn Error); /// /// let mut iter = err.iter_sources(); /// /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); /// assert!(iter.next().is_none()); /// assert!(iter.next().is_none()); /// ``` /// /// [`source`]: trait.Error.html#method.source #[inline] #[unstable(feature = "error_iter", issue = "58520")] pub fn iter_sources(&self) -> ErrorIter<'_> { ErrorIter { current: self.source(), } } } /// An iterator over [`Error`] /// /// [`Error`]: trait.Error.html #[unstable(feature = "error_iter", issue = "58520")] #[derive(Copy, Clone, Debug)] pub struct ErrorIter<'a> { current: Option<&'a (dyn Error + 'static)>, } #[unstable(feature = "error_iter", issue = "58520")] impl<'a> Iterator for ErrorIter<'a> { type Item = &'a (dyn Error + 'static); fn next(&mut self) -> Option { let current = self.current; self.current = self.current.and_then(Error::source); current } } impl dyn Error + Send { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] /// Attempt to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; ::downcast(err).map_err(|s| unsafe { // reapply the Send marker transmute::, Box>(s) }) } } impl dyn Error + Send + Sync { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] /// Attempt to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; ::downcast(err).map_err(|s| unsafe { // reapply the Send+Sync marker transmute::, Box>(s) }) } } #[cfg(test)] mod tests { use super::Error; use crate::fmt; #[derive(Debug, PartialEq)] struct A; #[derive(Debug, PartialEq)] struct B; impl fmt::Display for A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A") } } impl fmt::Display for B { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "B") } } impl Error for A { fn description(&self) -> &str { "A-desc" } } impl Error for B { fn description(&self) -> &str { "A-desc" } } #[test] fn downcasting() { let mut a = A; let a = &mut a as &mut (dyn Error + 'static); assert_eq!(a.downcast_ref::(), Some(&A)); assert_eq!(a.downcast_ref::(), None); assert_eq!(a.downcast_mut::(), Some(&mut A)); assert_eq!(a.downcast_mut::(), None); let a: Box = Box::new(A); match a.downcast::() { Ok(..) => panic!("expected error"), Err(e) => assert_eq!(*e.downcast::().unwrap(), A), } } }