| #![doc = include_str!("error.md")] |
| #![unstable(feature = "error_in_core", issue = "none")] |
| |
| #[cfg(test)] |
| mod tests; |
| |
| use crate::any::{Demand, Provider, TypeId}; |
| use crate::fmt::{Debug, Display}; |
| |
| /// `Error` is a trait representing the basic expectations for error values, |
| /// i.e., values of type `E` in [`Result<T, E>`]. |
| /// |
| /// Errors must describe themselves through the [`Display`] and [`Debug`] |
| /// traits. Error messages are typically concise lowercase sentences without |
| /// trailing punctuation: |
| /// |
| /// ``` |
| /// let err = "NaN".parse::<u32>().unwrap_err(); |
| /// assert_eq!(err.to_string(), "invalid digit found in string"); |
| /// ``` |
| /// |
| /// Errors may provide cause information. [`Error::source()`] 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 |
| /// accessing that error via [`Error::source()`]. This makes it possible for the |
| /// high-level module to provide its own errors while also revealing some of the |
| /// implementation for debugging. |
| #[stable(feature = "rust1", since = "1.0.0")] |
| #[cfg_attr(not(test), rustc_diagnostic_item = "Error")] |
| #[rustc_has_incoherent_inherent_impls] |
| pub trait Error: Debug + Display { |
| /// The lower-level source of this error, if any. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::error::Error; |
| /// use std::fmt; |
| /// |
| /// #[derive(Debug)] |
| /// struct SuperError { |
| /// source: 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 source(&self) -> Option<&(dyn Error + 'static)> { |
| /// Some(&self.source) |
| /// } |
| /// } |
| /// |
| /// #[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 get_super_error() -> Result<(), SuperError> { |
| /// Err(SuperError { source: SuperErrorSideKick }) |
| /// } |
| /// |
| /// fn main() { |
| /// match get_super_error() { |
| /// Err(e) => { |
| /// println!("Error: {e}"); |
| /// 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::<Self>() |
| } |
| |
| /// ``` |
| /// if let Err(e) = "xc".parse::<u32>() { |
| /// // Print `e` itself, no need for description(). |
| /// eprintln!("Error: {e}"); |
| /// } |
| /// ``` |
| #[stable(feature = "rust1", since = "1.0.0")] |
| #[deprecated(since = "1.42.0", note = "use the Display impl or to_string()")] |
| fn description(&self) -> &str { |
| "description() is deprecated; use Display" |
| } |
| |
| #[stable(feature = "rust1", since = "1.0.0")] |
| #[deprecated( |
| since = "1.33.0", |
| note = "replaced by Error::source, which can support downcasting" |
| )] |
| #[allow(missing_docs)] |
| fn cause(&self) -> Option<&dyn Error> { |
| self.source() |
| } |
| |
| /// Provides type based access to context intended for error reports. |
| /// |
| /// Used in conjunction with [`Demand::provide_value`] and [`Demand::provide_ref`] to extract |
| /// references to member variables from `dyn Error` trait objects. |
| /// |
| /// # Example |
| /// |
| /// ```rust |
| /// #![feature(provide_any)] |
| /// #![feature(error_generic_member_access)] |
| /// use core::fmt; |
| /// use core::any::Demand; |
| /// |
| /// #[derive(Debug)] |
| /// struct MyBacktrace { |
| /// // ... |
| /// } |
| /// |
| /// impl MyBacktrace { |
| /// fn new() -> MyBacktrace { |
| /// // ... |
| /// # MyBacktrace {} |
| /// } |
| /// } |
| /// |
| /// #[derive(Debug)] |
| /// struct SourceError { |
| /// // ... |
| /// } |
| /// |
| /// impl fmt::Display for SourceError { |
| /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| /// write!(f, "Example Source Error") |
| /// } |
| /// } |
| /// |
| /// impl std::error::Error for SourceError {} |
| /// |
| /// #[derive(Debug)] |
| /// struct Error { |
| /// source: SourceError, |
| /// backtrace: MyBacktrace, |
| /// } |
| /// |
| /// impl fmt::Display for Error { |
| /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| /// write!(f, "Example Error") |
| /// } |
| /// } |
| /// |
| /// impl std::error::Error for Error { |
| /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { |
| /// demand |
| /// .provide_ref::<MyBacktrace>(&self.backtrace) |
| /// .provide_ref::<dyn std::error::Error + 'static>(&self.source); |
| /// } |
| /// } |
| /// |
| /// fn main() { |
| /// let backtrace = MyBacktrace::new(); |
| /// let source = SourceError {}; |
| /// let error = Error { source, backtrace }; |
| /// let dyn_error = &error as &dyn std::error::Error; |
| /// let backtrace_ref = dyn_error.request_ref::<MyBacktrace>().unwrap(); |
| /// |
| /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); |
| /// } |
| /// ``` |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| #[allow(unused_variables)] |
| fn provide<'a>(&'a self, demand: &mut Demand<'a>) {} |
| } |
| |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| impl<E> Provider for E |
| where |
| E: Error + ?Sized, |
| { |
| fn provide<'a>(&'a self, demand: &mut Demand<'a>) { |
| self.provide(demand) |
| } |
| } |
| |
| 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; |
| } |
| |
| #[unstable(feature = "never_type", issue = "35121")] |
| impl Error for ! {} |
| |
| impl<'a> dyn Error + 'a { |
| /// Request a reference of type `T` as context about this error. |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| pub fn request_ref<T: ?Sized + 'static>(&'a self) -> Option<&'a T> { |
| core::any::request_ref(self) |
| } |
| |
| /// Request a value of type `T` as context about this error. |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| pub fn request_value<T: 'static>(&'a self) -> Option<T> { |
| core::any::request_value(self) |
| } |
| } |
| |
| // Copied from `any.rs`. |
| impl dyn Error + 'static { |
| /// Returns `true` if the inner type is the same as `T`. |
| #[stable(feature = "error_downcast", since = "1.3.0")] |
| #[inline] |
| pub fn is<T: Error + 'static>(&self) -> bool { |
| // Get `TypeId` of the type this function is instantiated with. |
| let t = TypeId::of::<T>(); |
| |
| // Get `TypeId` of the type in the trait object (`self`). |
| let concrete = self.type_id(private::Internal); |
| |
| // Compare both `TypeId`s on equality. |
| t == concrete |
| } |
| |
| /// Returns some reference to the inner 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<T: Error + 'static>(&self) -> Option<&T> { |
| if self.is::<T>() { |
| // SAFETY: `is` ensures this type cast is correct |
| unsafe { Some(&*(self as *const dyn Error as *const T)) } |
| } else { |
| None |
| } |
| } |
| |
| /// Returns some mutable reference to the inner 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<T: Error + 'static>(&mut self) -> Option<&mut T> { |
| if self.is::<T>() { |
| // SAFETY: `is` ensures this type cast is correct |
| 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 `dyn Error`. |
| #[stable(feature = "error_downcast", since = "1.3.0")] |
| #[inline] |
| pub fn is<T: Error + 'static>(&self) -> bool { |
| <dyn Error + 'static>::is::<T>(self) |
| } |
| |
| /// Forwards to the method defined on the type `dyn Error`. |
| #[stable(feature = "error_downcast", since = "1.3.0")] |
| #[inline] |
| pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { |
| <dyn Error + 'static>::downcast_ref::<T>(self) |
| } |
| |
| /// Forwards to the method defined on the type `dyn Error`. |
| #[stable(feature = "error_downcast", since = "1.3.0")] |
| #[inline] |
| pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
| <dyn Error + 'static>::downcast_mut::<T>(self) |
| } |
| |
| /// Request a reference of type `T` as context about this error. |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { |
| <dyn Error>::request_ref(self) |
| } |
| |
| /// Request a value of type `T` as context about this error. |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| pub fn request_value<T: 'static>(&self) -> Option<T> { |
| <dyn Error>::request_value(self) |
| } |
| } |
| |
| impl dyn Error + 'static + Send + Sync { |
| /// Forwards to the method defined on the type `dyn Error`. |
| #[stable(feature = "error_downcast", since = "1.3.0")] |
| #[inline] |
| pub fn is<T: Error + 'static>(&self) -> bool { |
| <dyn Error + 'static>::is::<T>(self) |
| } |
| |
| /// Forwards to the method defined on the type `dyn Error`. |
| #[stable(feature = "error_downcast", since = "1.3.0")] |
| #[inline] |
| pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { |
| <dyn Error + 'static>::downcast_ref::<T>(self) |
| } |
| |
| /// Forwards to the method defined on the type `dyn Error`. |
| #[stable(feature = "error_downcast", since = "1.3.0")] |
| #[inline] |
| pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
| <dyn Error + 'static>::downcast_mut::<T>(self) |
| } |
| |
| /// Request a reference of type `T` as context about this error. |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { |
| <dyn Error>::request_ref(self) |
| } |
| |
| /// Request a value of type `T` as context about this error. |
| #[unstable(feature = "error_generic_member_access", issue = "99301")] |
| pub fn request_value<T: 'static>(&self) -> Option<T> { |
| <dyn Error>::request_value(self) |
| } |
| } |
| |
| impl dyn Error { |
| /// Returns an iterator starting with the current error and continuing with |
| /// recursively calling [`Error::source`]. |
| /// |
| /// If you want to omit the current error and only use its sources, |
| /// use `skip(1)`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// #![feature(error_iter)] |
| /// use std::error::Error; |
| /// use std::fmt; |
| /// |
| /// #[derive(Debug)] |
| /// struct A; |
| /// |
| /// #[derive(Debug)] |
| /// struct B(Option<Box<dyn Error + 'static>>); |
| /// |
| /// 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<Error> = b.into(); // or |
| /// let err = &b as &(dyn Error); |
| /// |
| /// let mut iter = err.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()); |
| /// ``` |
| #[unstable(feature = "error_iter", issue = "58520")] |
| #[inline] |
| pub fn sources(&self) -> Source<'_> { |
| // You may think this method would be better in the Error trait, and you'd be right. |
| // Unfortunately that doesn't work, not because of the object safety rules but because we |
| // save a reference to self in Sources below as a trait object. If this method was |
| // declared in Error, then self would have the type &T where T is some concrete type which |
| // implements Error. We would need to coerce self to have type &dyn Error, but that requires |
| // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error |
| // since that would forbid Error trait objects, and we can't put that bound on the method |
| // because that means the method can't be called on trait objects (we'd also need the |
| // 'static bound, but that isn't allowed because methods with bounds on Self other than |
| // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible. |
| |
| Source { current: Some(self) } |
| } |
| } |
| |
| /// An iterator over an [`Error`] and its sources. |
| /// |
| /// If you want to omit the initial error and only process |
| /// its sources, use `skip(1)`. |
| #[unstable(feature = "error_iter", issue = "58520")] |
| #[derive(Clone, Debug)] |
| pub struct Source<'a> { |
| current: Option<&'a (dyn Error + 'static)>, |
| } |
| |
| #[unstable(feature = "error_iter", issue = "58520")] |
| impl<'a> Iterator for Source<'a> { |
| type Item = &'a (dyn Error + 'static); |
| |
| fn next(&mut self) -> Option<Self::Item> { |
| let current = self.current; |
| self.current = self.current.and_then(Error::source); |
| current |
| } |
| } |
| |
| #[stable(feature = "error_by_ref", since = "1.51.0")] |
| impl<'a, T: Error + ?Sized> Error for &'a T { |
| #[allow(deprecated, deprecated_in_future)] |
| fn description(&self) -> &str { |
| Error::description(&**self) |
| } |
| |
| #[allow(deprecated)] |
| fn cause(&self) -> Option<&dyn Error> { |
| Error::cause(&**self) |
| } |
| |
| fn source(&self) -> Option<&(dyn Error + 'static)> { |
| Error::source(&**self) |
| } |
| |
| fn provide<'b>(&'b self, demand: &mut Demand<'b>) { |
| Error::provide(&**self, demand); |
| } |
| } |
| |
| #[stable(feature = "fmt_error", since = "1.11.0")] |
| impl Error for crate::fmt::Error { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "an error occurred when formatting an argument" |
| } |
| } |
| |
| #[stable(feature = "try_borrow", since = "1.13.0")] |
| impl Error for crate::cell::BorrowError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "already mutably borrowed" |
| } |
| } |
| |
| #[stable(feature = "try_borrow", since = "1.13.0")] |
| impl Error for crate::cell::BorrowMutError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "already borrowed" |
| } |
| } |
| |
| #[stable(feature = "try_from", since = "1.34.0")] |
| impl Error for crate::char::CharTryFromError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "converted integer out of range for `char`" |
| } |
| } |
| |
| #[stable(feature = "char_from_str", since = "1.20.0")] |
| impl Error for crate::char::ParseCharError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| #[stable(feature = "duration_checked_float", since = "1.66.0")] |
| impl Error for crate::time::TryFromFloatSecsError {} |
| |
| #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] |
| impl Error for crate::ffi::FromBytesWithNulError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] |
| impl Error for crate::ffi::FromBytesUntilNulError {} |