| // 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.. |
| |
| #[cfg(feature = "backtrace")] |
| use crate::backtrace::Backtrace; |
| use core::alloc::{AllocError, LayoutErr}; |
| use core::array; |
| use core::any::TypeId; |
| use core::cell; |
| use core::char; |
| use core::fmt::{self, Debug, Display}; |
| use core::mem::transmute; |
| use core::num; |
| use alloc_crate::str; |
| use alloc_crate::string::{self, String}; |
| use alloc_crate::boxed::Box; |
| use alloc_crate::borrow::Cow; |
| use alloc_crate::collections; |
| |
| /// `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, 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<T, E>`]: ../result/enum.Result.html |
| /// [`Display`]: ../fmt/trait.Display.html |
| /// [`Debug`]: ../fmt/trait.Debug.html |
| /// [`source`]: trait.Error.html#method.source |
| pub trait Error: Debug + Display { |
| /// The lower-level source of this error, if any. |
| /// |
| fn source(&self) -> Option<&(dyn Error + 'static)> { |
| None |
| } |
| |
| /// Gets the `TypeId` of `self`. |
| 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" |
| } |
| |
| 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`]. |
| /// |
| /// [`Error`]: ../error/trait.Error.html |
| /// |
| 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`]. |
| /// |
| /// [`Error`]: ../error/trait.Error.html |
| /// |
| 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`]. |
| /// |
| fn from(err: String) -> Box<dyn Error + Send + Sync> { |
| 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)) |
| } |
| } |
| |
| impl From<String> for Box<dyn Error> { |
| /// Converts a [`String`] into a box of dyn [`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`]. |
| /// |
| #[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`]. |
| /// |
| 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`]. |
| /// |
| /// [`Cow`]: ../borrow/enum.Cow.html |
| /// [`Error`]: ../error/trait.Error.html |
| /// |
| 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`]. |
| /// |
| /// [`Cow`]: ../borrow/enum.Cow.html |
| /// [`Error`]: ../error/trait.Error.html |
| /// |
| fn from(err: Cow<'a, str>) -> Box<dyn Error> { |
| From::from(String::from(err)) |
| } |
| } |
| |
| impl Error for ! { |
| fn description(&self) -> &str { |
| *self |
| } |
| } |
| |
| impl Error for AllocError { |
| fn description(&self) -> &str { |
| "memory allocation failed" |
| } |
| } |
| |
| impl Error for LayoutErr { |
| fn description(&self) -> &str { |
| "invalid parameters to Layout::from_size_align" |
| } |
| } |
| |
| impl Error for str::ParseBoolError { |
| fn description(&self) -> &str { |
| "failed to parse bool" |
| } |
| } |
| |
| impl Error for str::Utf8Error { |
| fn description(&self) -> &str { |
| "invalid utf-8: corrupt contents" |
| } |
| } |
| |
| impl Error for num::ParseIntError { |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for num::TryFromIntError { |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for array::TryFromSliceError { |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for num::ParseFloatError { |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for string::FromUtf8Error { |
| fn description(&self) -> &str { |
| "invalid utf-8" |
| } |
| } |
| |
| impl Error for string::FromUtf16Error { |
| fn description(&self) -> &str { |
| "invalid utf-16" |
| } |
| } |
| |
| impl Error for string::ParseError { |
| fn description(&self) -> &str { |
| match *self {} |
| } |
| } |
| |
| impl Error for char::DecodeUtf16Error { |
| fn description(&self) -> &str { |
| "unpaired surrogate found" |
| } |
| } |
| |
| impl<T: Error> Error for Box<T> { |
| 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 Error for fmt::Error { |
| fn description(&self) -> &str { |
| "an error occurred when formatting an argument" |
| } |
| } |
| |
| impl Error for cell::BorrowError { |
| fn description(&self) -> &str { |
| "already mutably borrowed" |
| } |
| } |
| |
| impl Error for cell::BorrowMutError { |
| fn description(&self) -> &str { |
| "already borrowed" |
| } |
| } |
| |
| impl Error for char::CharTryFromError { |
| fn description(&self) -> &str { |
| "converted integer out of range for `char`" |
| } |
| } |
| |
| impl Error for char::ParseCharError { |
| fn description(&self) -> &str { |
| self.__description() |
| } |
| } |
| |
| impl Error for collections::TryReserveError {} |
| |
| // Copied from `any.rs`. |
| impl dyn Error + 'static { |
| /// Returns `true` if the boxed 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. |
| let boxed = self.type_id(private::Internal); |
| |
| // Compare both `TypeId`s on equality. |
| t == boxed |
| } |
| |
| /// Returns some reference to the boxed 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 boxed 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 [`source`]. |
| /// |
| /// If you want to omit the current error and only use its sources, |
| /// use `skip(1)`. |
| /// |
| #[inline] |
| pub fn chain(&self) -> Chain<'_> { |
| Chain { current: Some(self) } |
| } |
| |
| /// Returns an iterator starting with the current error and continuing with |
| /// recursively calling [`source`]. |
| /// |
| #[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`]. |
| /// |
| #[inline] |
| pub fn iter_sources(&self) -> ErrorIter<'_> { |
| ErrorIter { |
| current: self.source(), |
| } |
| } |
| } |
| |
| /// An iterator over an [`Error`] and its sources. |
| /// |
| /// If you want to omit the initial error and only process |
| /// its sources, use `skip(1)`. |
| /// |
| /// [`Error`]: trait.Error.html |
| #[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 |
| } |
| } |
| |
| /// An iterator over an [`Error`] and its sources. |
| /// |
| /// [`Error`]: trait.Error.html |
| #[derive(Copy, Clone, Debug)] |
| pub struct ErrorIter<'a> { |
| current: Option<&'a (dyn Error + 'static)>, |
| } |
| |
| impl<'a> Iterator for ErrorIter<'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) |
| }) |
| } |
| } |
| |