| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License.. |
| |
| //! Traits for working with Errors. |
| |
| #[cfg(feature = "unit_test")] |
| mod tests; |
| |
| // 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 core::convert::Infallible; |
| |
| use crate::alloc::{AllocError, LayoutError}; |
| use crate::any::TypeId; |
| #[cfg(feature = "backtrace")] |
| use crate::backtrace::Backtrace; |
| use crate::borrow::Cow; |
| use crate::cell; |
| use crate::char; |
| use crate::fmt::{self, Debug, Display}; |
| #[cfg(feature = "backtrace")] |
| use crate::fmt::Write; |
| use crate::mem::transmute; |
| use crate::num; |
| use crate::str; |
| use crate::string; |
| use crate::sync::Arc; |
| use crate::sys; |
| use crate::time; |
| |
| use sgx_oc::ocall::{self, OCallError}; |
| use sgx_types::error::SgxStatus; |
| |
| /// `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 chain 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 via `source` chains. |
| 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"), |
| /// } |
| /// } |
| /// ``` |
| fn source(&self) -> Option<&(dyn Error + 'static)> { |
| None |
| } |
| |
| /// Gets the `TypeId` of `self`. |
| #[doc(hidden)] |
| fn type_id(&self, _: private::Internal) -> TypeId |
| where |
| Self: 'static, |
| { |
| TypeId::of::<Self>() |
| } |
| |
| /// Returns a stack backtrace, if available, of where this error occurred. |
| /// |
| /// This function allows inspecting the location, in code, of where an error |
| /// happened. The returned `Backtrace` contains information about the stack |
| /// trace of the OS thread of execution of where the error originated from. |
| /// |
| /// Note that not all errors contain a `Backtrace`. Also note that a |
| /// `Backtrace` may actually be empty. For more information consult the |
| /// `Backtrace` type itself. |
| #[cfg(feature = "backtrace")] |
| fn backtrace(&self) -> Option<&Backtrace> { |
| None |
| } |
| |
| /// ``` |
| /// if let Err(e) = "xc".parse::<u32>() { |
| /// // Print `e` itself, no need for description(). |
| /// eprintln!("Error: {}", e); |
| /// } |
| /// ``` |
| fn description(&self) -> &str { |
| "description() is deprecated; use Display" |
| } |
| |
| #[allow(missing_docs)] |
| fn cause(&self) -> Option<&dyn Error> { |
| self.source() |
| } |
| } |
| |
| mod private { |
| // This is a hack to prevent `type_id` from being overridden by `Error` |
| // implementations, since that can enable unsound downcasting. |
| #[derive(Debug)] |
| pub struct Internal; |
| } |
| |
| impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> { |
| /// Converts a type of [`Error`] into a box of dyn [`Error`]. |
| /// |
| /// # 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 {} |
| /// |
| /// let an_error = AnError; |
| /// assert!(0 == mem::size_of_val(&an_error)); |
| /// let a_boxed_error = Box::<dyn Error>::from(an_error); |
| /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| fn from(err: E) -> Box<dyn Error + 'a> { |
| Box::new(err) |
| } |
| } |
| |
| impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> { |
| /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of |
| /// dyn [`Error`] + [`Send`] + [`Sync`]. |
| /// |
| /// # 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 {} |
| /// |
| /// 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::<dyn Error + Send + Sync>::from(an_error); |
| /// assert!( |
| /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> { |
| Box::new(err) |
| } |
| } |
| |
| impl From<String> for Box<dyn Error + Send + Sync> { |
| /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::error::Error; |
| /// use std::mem; |
| /// |
| /// let a_string_error = "a string error".to_string(); |
| /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error); |
| /// assert!( |
| /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| #[inline] |
| fn from(err: String) -> Box<dyn Error + Send + Sync> { |
| struct StringError(String); |
| |
| impl Error for StringError { |
| #[allow(deprecated)] |
| 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)) |
| } |
| } |
| |
| impl From<String> for Box<dyn Error> { |
| /// Converts a [`String`] into a box of dyn [`Error`]. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::error::Error; |
| /// use std::mem; |
| /// |
| /// let a_string_error = "a string error".to_string(); |
| /// let a_boxed_error = Box::<dyn Error>::from(a_string_error); |
| /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| fn from(str_err: String) -> Box<dyn Error> { |
| let err1: Box<dyn Error + Send + Sync> = From::from(str_err); |
| let err2: Box<dyn Error> = err1; |
| err2 |
| } |
| } |
| |
| impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> { |
| /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. |
| /// |
| /// [`str`]: prim@str |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::error::Error; |
| /// use std::mem; |
| /// |
| /// let a_str_error = "a str error"; |
| /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error); |
| /// assert!( |
| /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| #[inline] |
| fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> { |
| From::from(String::from(err)) |
| } |
| } |
| |
| impl From<&str> for Box<dyn Error> { |
| /// Converts a [`str`] into a box of dyn [`Error`]. |
| /// |
| /// [`str`]: prim@str |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::error::Error; |
| /// use std::mem; |
| /// |
| /// let a_str_error = "a str error"; |
| /// let a_boxed_error = Box::<dyn Error>::from(a_str_error); |
| /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| fn from(err: &str) -> Box<dyn Error> { |
| From::from(String::from(err)) |
| } |
| } |
| |
| impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> { |
| /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. |
| /// |
| /// # 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::<dyn Error + Send + Sync>::from(a_cow_str_error); |
| /// assert!( |
| /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> { |
| From::from(String::from(err)) |
| } |
| } |
| |
| impl<'a> From<Cow<'a, str>> for Box<dyn Error> { |
| /// Converts a [`Cow`] into a box of dyn [`Error`]. |
| /// |
| /// # 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::<dyn Error>::from(a_cow_str_error); |
| /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error)) |
| /// ``` |
| fn from(err: Cow<'a, str>) -> Box<dyn Error> { |
| From::from(String::from(err)) |
| } |
| } |
| |
| impl Error for ! {} |
| |
| impl Error for AllocError {} |
| |
| impl Error for LayoutError {} |
| |
| impl Error for str::ParseBoolError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "failed to parse bool" |
| } |
| } |
| |
| impl Error for str::Utf8Error { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "invalid utf-8: corrupt contents" |
| } |
| } |
| |
| impl Error for num::ParseIntError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for num::TryFromIntError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for array::TryFromSliceError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for num::ParseFloatError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for string::FromUtf8Error { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "invalid utf-8" |
| } |
| } |
| |
| impl Error for string::FromUtf16Error { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "invalid utf-16" |
| } |
| } |
| |
| impl Error for Infallible { |
| fn description(&self) -> &str { |
| match *self {} |
| } |
| } |
| |
| impl Error for char::DecodeUtf16Error { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "unpaired surrogate found" |
| } |
| } |
| |
| impl Error for char::TryFromCharError {} |
| |
| impl<'a, K: Debug + Ord, V: Debug> Error |
| for crate::collections::btree_map::OccupiedError<'a, K, V> |
| { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "key already exists" |
| } |
| } |
| |
| impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "key already exists" |
| } |
| } |
| |
| impl Error for SgxStatus { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for OCallError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| match self { |
| OCallError::SgxError(s) => s.description(), |
| OCallError::OsError(code) => sys::decode_error_kind(*code).as_str(), |
| OCallError::GaiError(code) => ocall::gai_error_str(*code), |
| OCallError::CustomError(s) => s, |
| } |
| } |
| |
| #[allow(deprecated)] |
| fn source(&self) -> Option<&(dyn Error + 'static)> { |
| match self { |
| OCallError::SgxError(ref s) => Some(s), |
| OCallError::OsError(..) => None, |
| OCallError::GaiError(..) => None, |
| OCallError::CustomError(..) => None, |
| } |
| } |
| } |
| |
| impl<T: Error> Error for Box<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) |
| } |
| } |
| |
| 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) |
| } |
| |
| #[cfg(feature = "backtrace")] |
| fn backtrace(&self) -> Option<&Backtrace> { |
| Error::backtrace(&**self) |
| } |
| } |
| |
| impl<T: Error + ?Sized> Error for Arc<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) |
| } |
| |
| #[cfg(feature = "backtrace")] |
| fn backtrace(&self) -> Option<&Backtrace> { |
| Error::backtrace(&**self) |
| } |
| } |
| |
| impl Error for fmt::Error { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "an error occurred when formatting an argument" |
| } |
| } |
| |
| impl Error for cell::BorrowError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "already mutably borrowed" |
| } |
| } |
| |
| impl Error for cell::BorrowMutError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "already borrowed" |
| } |
| } |
| |
| impl Error for char::CharTryFromError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| "converted integer out of range for `char`" |
| } |
| } |
| |
| impl Error for char::ParseCharError { |
| #[allow(deprecated)] |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for alloc_crate::collections::TryReserveError {} |
| |
| impl Error for time::FromFloatSecsError {} |
| |
| // Copied from `any.rs`. |
| impl dyn Error + 'static { |
| /// Returns `true` if the inner type is the same as `T`. |
| #[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. |
| #[inline] |
| pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { |
| if self.is::<T>() { |
| 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. |
| #[inline] |
| pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
| if self.is::<T>() { |
| 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`. |
| #[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`. |
| #[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`. |
| #[inline] |
| pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
| <dyn Error + 'static>::downcast_mut::<T>(self) |
| } |
| } |
| |
| impl dyn Error + 'static + Send + Sync { |
| /// Forwards to the method defined on the type `dyn Error`. |
| #[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`. |
| #[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`. |
| #[inline] |
| pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { |
| <dyn Error + 'static>::downcast_mut::<T>(self) |
| } |
| } |
| |
| impl dyn Error { |
| #[inline] |
| /// Attempts to downcast the box to a concrete type. |
| pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> { |
| if self.is::<T>() { |
| 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 [`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.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()); |
| /// ``` |
| #[inline] |
| pub fn chain(&self) -> Chain<'_> { |
| Chain { 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)`. |
| #[derive(Clone, Debug)] |
| pub struct Chain<'a> { |
| current: Option<&'a (dyn Error + 'static)>, |
| } |
| |
| impl<'a> Iterator for Chain<'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 |
| } |
| } |
| |
| impl dyn Error + Send { |
| #[inline] |
| /// Attempts to downcast the box to a concrete type. |
| pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> { |
| let err: Box<dyn Error> = self; |
| <dyn Error>::downcast(err).map_err(|s| unsafe { |
| // Reapply the `Send` marker. |
| transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s) |
| }) |
| } |
| } |
| |
| impl dyn Error + Send + Sync { |
| #[inline] |
| /// Attempts to downcast the box to a concrete type. |
| pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> { |
| let err: Box<dyn Error> = self; |
| <dyn Error>::downcast(err).map_err(|s| unsafe { |
| // Reapply the `Send + Sync` marker. |
| transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s) |
| }) |
| } |
| } |
| |
| /// An error reporter that print's an error and its sources. |
| /// |
| /// Report also exposes configuration options for formatting the error chain, either entirely on a |
| /// single line, or in multi-line format with each cause in the error chain on a new line. |
| /// |
| /// `Report` only requires that the wrapped error implements `Error`. It doesn't require that the |
| /// wrapped error be `Send`, `Sync`, or `'static`. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// #![feature(error_reporter)] |
| /// use std::error::{Error, Report}; |
| /// 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: {}", Report::new(e)), |
| /// _ => println!("No error"), |
| /// } |
| /// } |
| /// ``` |
| /// |
| /// This example produces the following output: |
| /// |
| /// ```console |
| /// Error: SuperError is here!: SuperErrorSideKick is here! |
| /// ``` |
| /// |
| /// ## Output consistency |
| /// |
| /// Report prints the same output via `Display` and `Debug`, so it works well with |
| /// [`Result::unwrap`]/[`Result::expect`] which print their `Err` variant via `Debug`: |
| /// |
| /// ```should_panic |
| /// #![feature(error_reporter)] |
| /// use std::error::Report; |
| /// # 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 }) |
| /// # } |
| /// |
| /// get_super_error().map_err(Report::new).unwrap(); |
| /// ``` |
| /// |
| /// This example produces the following output: |
| /// |
| /// ```console |
| /// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!', src/error.rs:34:40 |
| /// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace |
| /// ``` |
| /// |
| /// ## Return from `main` |
| /// |
| /// `Report` also implements `From` for all types that implement [`Error`], this when combined with |
| /// the `Debug` output means `Report` is an ideal starting place for formatting errors returned |
| /// from `main`. |
| /// |
| /// ```should_panic |
| /// #![feature(error_reporter)] |
| /// use std::error::Report; |
| /// # 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() -> Result<(), Report> { |
| /// get_super_error()?; |
| /// Ok(()) |
| /// } |
| /// ``` |
| /// |
| /// This example produces the following output: |
| /// |
| /// ```console |
| /// Error: SuperError is here!: SuperErrorSideKick is here! |
| /// ``` |
| /// |
| /// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line |
| /// output format, if you want to make sure your `Report`s are pretty printed and include backtrace |
| /// you will need to manually convert and enable those flags. |
| /// |
| /// ```should_panic |
| /// #![feature(error_reporter)] |
| /// use std::error::Report; |
| /// # 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() -> Result<(), Report> { |
| /// get_super_error() |
| /// .map_err(Report::from) |
| /// .map_err(|r| r.pretty(true).show_backtrace(true))?; |
| /// Ok(()) |
| /// } |
| /// ``` |
| /// |
| /// This example produces the following output: |
| /// |
| /// ```console |
| /// Error: SuperError is here! |
| /// |
| /// Caused by: |
| /// SuperErrorSideKick is here! |
| /// ``` |
| #[cfg(feature = "backtrace")] |
| pub struct Report<E = Box<dyn Error>> { |
| /// The error being reported. |
| error: E, |
| /// Whether a backtrace should be included as part of the report. |
| show_backtrace: bool, |
| /// Whether the report should be pretty-printed. |
| pretty: bool, |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl<E> Report<E> |
| where |
| Report<E>: From<E>, |
| { |
| /// Create a new `Report` from an input error. |
| pub fn new(error: E) -> Report<E> { |
| Self::from(error) |
| } |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl<E> Report<E> { |
| /// Enable pretty-printing the report across multiple lines. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// #![feature(error_reporter)] |
| /// use std::error::Report; |
| /// # 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 {} |
| /// |
| /// let error = SuperError { source: SuperErrorSideKick }; |
| /// let report = Report::new(error).pretty(true); |
| /// eprintln!("Error: {:?}", report); |
| /// ``` |
| /// |
| /// This example produces the following output: |
| /// |
| /// ```console |
| /// Error: SuperError is here! |
| /// |
| /// Caused by: |
| /// SuperErrorSideKick is here! |
| /// ``` |
| /// |
| /// When there are multiple source errors the causes will be numbered in order of iteration |
| /// starting from the outermost error. |
| /// |
| /// ```rust |
| /// #![feature(error_reporter)] |
| /// use std::error::Report; |
| /// # 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 { |
| /// # source: SuperErrorSideKickSideKick, |
| /// # } |
| /// # impl fmt::Display for SuperErrorSideKick { |
| /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| /// # write!(f, "SuperErrorSideKick is here!") |
| /// # } |
| /// # } |
| /// # impl Error for SuperErrorSideKick { |
| /// # fn source(&self) -> Option<&(dyn Error + 'static)> { |
| /// # Some(&self.source) |
| /// # } |
| /// # } |
| /// # #[derive(Debug)] |
| /// # struct SuperErrorSideKickSideKick; |
| /// # impl fmt::Display for SuperErrorSideKickSideKick { |
| /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| /// # write!(f, "SuperErrorSideKickSideKick is here!") |
| /// # } |
| /// # } |
| /// # impl Error for SuperErrorSideKickSideKick { } |
| /// |
| /// let source = SuperErrorSideKickSideKick; |
| /// let source = SuperErrorSideKick { source }; |
| /// let error = SuperError { source }; |
| /// let report = Report::new(error).pretty(true); |
| /// eprintln!("Error: {:?}", report); |
| /// ``` |
| /// |
| /// This example produces the following output: |
| /// |
| /// ```console |
| /// Error: SuperError is here! |
| /// |
| /// Caused by: |
| /// 0: SuperErrorSideKick is here! |
| /// 1: SuperErrorSideKickSideKick is here! |
| /// ``` |
| pub fn pretty(mut self, pretty: bool) -> Self { |
| self.pretty = pretty; |
| self |
| } |
| |
| /// Display backtrace if available when using pretty output format. |
| /// |
| /// # Examples |
| /// |
| /// **Note**: Report will search for the first `Backtrace` it can find starting from the |
| /// outermost error. In this example it will display the backtrace from the second error in the |
| /// chain, `SuperErrorSideKick`. |
| /// |
| /// ```rust |
| /// #![feature(error_reporter)] |
| /// #![feature(backtrace)] |
| /// # use std::error::Error; |
| /// # use std::fmt; |
| /// use std::error::Report; |
| /// use std::backtrace::Backtrace; |
| /// |
| /// # #[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 { |
| /// backtrace: Backtrace, |
| /// } |
| /// |
| /// impl SuperErrorSideKick { |
| /// fn new() -> SuperErrorSideKick { |
| /// SuperErrorSideKick { backtrace: Backtrace::force_capture() } |
| /// } |
| /// } |
| /// |
| /// impl Error for SuperErrorSideKick { |
| /// fn backtrace(&self) -> Option<&Backtrace> { |
| /// Some(&self.backtrace) |
| /// } |
| /// } |
| /// |
| /// // The rest of the example is unchanged ... |
| /// # impl fmt::Display for SuperErrorSideKick { |
| /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| /// # write!(f, "SuperErrorSideKick is here!") |
| /// # } |
| /// # } |
| /// |
| /// let source = SuperErrorSideKick::new(); |
| /// let error = SuperError { source }; |
| /// let report = Report::new(error).pretty(true).show_backtrace(true); |
| /// eprintln!("Error: {:?}", report); |
| /// ``` |
| /// |
| /// This example produces something similar to the following output: |
| /// |
| /// ```console |
| /// Error: SuperError is here! |
| /// |
| /// Caused by: |
| /// SuperErrorSideKick is here! |
| /// |
| /// Stack backtrace: |
| /// 0: rust_out::main::_doctest_main_src_error_rs_1158_0::SuperErrorSideKick::new |
| /// 1: rust_out::main::_doctest_main_src_error_rs_1158_0 |
| /// 2: rust_out::main |
| /// 3: core::ops::function::FnOnce::call_once |
| /// 4: std::sys_common::backtrace::__rust_begin_short_backtrace |
| /// 5: std::rt::lang_start::{{closure}} |
| /// 6: std::panicking::try |
| /// 7: std::rt::lang_start_internal |
| /// 8: std::rt::lang_start |
| /// 9: main |
| /// 10: __libc_start_main |
| /// 11: _start |
| /// ``` |
| pub fn show_backtrace(mut self, show_backtrace: bool) -> Self { |
| self.show_backtrace = show_backtrace; |
| self |
| } |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl<E> Report<E> |
| where |
| E: Error, |
| { |
| fn backtrace(&self) -> Option<&Backtrace> { |
| // have to grab the backtrace on the first error directly since that error may not be |
| // 'static |
| let backtrace = self.error.backtrace(); |
| backtrace.or_else(|| { |
| self.error |
| .source() |
| .and_then(|source| source.chain().find_map(|source| source.backtrace())) |
| }) |
| } |
| |
| /// Format the report as a single line. |
| fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{}", self.error)?; |
| |
| let sources = self.error.source().into_iter().flat_map(<dyn Error>::chain); |
| |
| for cause in sources { |
| write!(f, ": {}", cause)?; |
| } |
| |
| Ok(()) |
| } |
| |
| /// Format the report as multiple lines, with each error cause on its own line. |
| fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| let error = &self.error; |
| |
| write!(f, "{}", error)?; |
| |
| if let Some(cause) = error.source() { |
| write!(f, "\n\nCaused by:")?; |
| |
| let multiple = cause.source().is_some(); |
| |
| for (ind, error) in cause.chain().enumerate() { |
| writeln!(f)?; |
| let mut indented = Indented { inner: f }; |
| if multiple { |
| write!(indented, "{: >4}: {}", ind, error)?; |
| } else { |
| write!(indented, " {}", error)?; |
| } |
| } |
| } |
| |
| if self.show_backtrace { |
| let backtrace = self.backtrace(); |
| |
| if let Some(backtrace) = backtrace { |
| let backtrace = backtrace.to_string(); |
| |
| f.write_str("\n\nStack backtrace:\n")?; |
| f.write_str(backtrace.trim_end())?; |
| } |
| } |
| |
| Ok(()) |
| } |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl Report<Box<dyn Error>> { |
| fn backtrace(&self) -> Option<&Backtrace> { |
| // have to grab the backtrace on the first error directly since that error may not be |
| // 'static |
| let backtrace = self.error.backtrace(); |
| backtrace.or_else(|| { |
| self.error |
| .source() |
| .and_then(|source| source.chain().find_map(|source| source.backtrace())) |
| }) |
| } |
| |
| /// Format the report as a single line. |
| fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{}", self.error)?; |
| |
| let sources = self.error.source().into_iter().flat_map(<dyn Error>::chain); |
| |
| for cause in sources { |
| write!(f, ": {}", cause)?; |
| } |
| |
| Ok(()) |
| } |
| |
| /// Format the report as multiple lines, with each error cause on its own line. |
| fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| let error = &self.error; |
| |
| write!(f, "{}", error)?; |
| |
| if let Some(cause) = error.source() { |
| write!(f, "\n\nCaused by:")?; |
| |
| let multiple = cause.source().is_some(); |
| |
| for (ind, error) in cause.chain().enumerate() { |
| writeln!(f)?; |
| let mut indented = Indented { inner: f }; |
| if multiple { |
| write!(indented, "{: >4}: {}", ind, error)?; |
| } else { |
| write!(indented, " {}", error)?; |
| } |
| } |
| } |
| |
| if self.show_backtrace { |
| let backtrace = self.backtrace(); |
| |
| if let Some(backtrace) = backtrace { |
| let backtrace = backtrace.to_string(); |
| |
| f.write_str("\n\nStack backtrace:\n")?; |
| f.write_str(backtrace.trim_end())?; |
| } |
| } |
| |
| Ok(()) |
| } |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl<E> From<E> for Report<E> |
| where |
| E: Error, |
| { |
| fn from(error: E) -> Self { |
| Report { error, show_backtrace: false, pretty: false } |
| } |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl<'a, E> From<E> for Report<Box<dyn Error + 'a>> |
| where |
| E: Error + 'a, |
| { |
| fn from(error: E) -> Self { |
| let error = box error; |
| Report { error, show_backtrace: false, pretty: false } |
| } |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl<E> fmt::Display for Report<E> |
| where |
| E: Error, |
| { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) } |
| } |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl fmt::Display for Report<Box<dyn Error>> { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) } |
| } |
| } |
| |
| // This type intentionally outputs the same format for `Display` and `Debug`for |
| // situations where you unwrap a `Report` or return it from main. |
| #[cfg(feature = "backtrace")] |
| impl<E> fmt::Debug for Report<E> |
| where |
| Report<E>: fmt::Display, |
| { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| fmt::Display::fmt(self, f) |
| } |
| } |
| |
| /// Wrapper type for indenting the inner source. |
| #[cfg(feature = "backtrace")] |
| struct Indented<'a, D> { |
| inner: &'a mut D, |
| } |
| |
| #[cfg(feature = "backtrace")] |
| impl<T> Write for Indented<'_, T> |
| where |
| T: Write, |
| { |
| fn write_str(&mut self, s: &str) -> fmt::Result { |
| for (i, line) in s.split('\n').enumerate() { |
| if i > 0 { |
| self.inner.write_char('\n')?; |
| self.inner.write_str(" ")?; |
| } |
| |
| self.inner.write_str(line)?; |
| } |
| |
| Ok(()) |
| } |
| } |