diff options
Diffstat (limited to 'src/libstd/error.rs')
| -rw-r--r-- | src/libstd/error.rs | 184 |
1 files changed, 86 insertions, 98 deletions
diff --git a/src/libstd/error.rs b/src/libstd/error.rs index eb5022ad577..29534696abc 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -9,34 +9,6 @@ // except according to those terms. //! Traits for working with Errors. -//! -//! # The `Error` trait -//! -//! `Error` is a trait representing the basic expectations for error values, -//! i.e. values of type `E` in [`Result<T, E>`]. At a minimum, errors must provide -//! a description, but they may optionally provide additional detail (via -//! [`Display`]) and cause chain information: -//! -//! ``` -//! use std::fmt::Display; -//! -//! trait Error: Display { -//! fn description(&self) -> &str; -//! -//! fn cause(&self) -> Option<&Error> { None } -//! } -//! ``` -//! -//! The [`cause`] method is generally used when errors cross "abstraction -//! boundaries", i.e. when a one module must report an error that is "caused" -//! by an error from a lower-level module. This setup makes it possible for the -//! high-level module to provide its own errors that do not commit to any -//! particular implementation, but also reveal some of its implementation for -//! debugging via [`cause`] chains. -//! -//! [`Result<T, E>`]: ../result/enum.Result.html -//! [`Display`]: ../fmt/trait.Display.html -//! [`cause`]: trait.Error.html#method.cause #![stable(feature = "rust1", since = "1.0.0")] @@ -51,12 +23,11 @@ // coherence challenge (e.g., specialization, neg impls, etc) we can // reconsider what crate these items belong in. -use alloc::allocator; +use alloc::{AllocErr, LayoutErr, CannotReallocInPlace}; use any::TypeId; use borrow::Cow; use cell; use char; -use convert; use core::array; use fmt::{self, Debug, Display}; use mem::transmute; @@ -64,33 +35,49 @@ use num; use str; use string; -/// Base functionality for all errors in Rust. +/// `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 [`cause`] method is generally used when errors cross "abstraction +/// boundaries", i.e. when a one module must report an error that is "caused" +/// by an error from a lower-level module. This setup makes it possible for the +/// high-level module to provide its own errors that do not commit to any +/// particular implementation, but also reveal some of its implementation for +/// debugging via [`cause`] chains. +/// +/// [`Result<T, E>`]: ../result/enum.Result.html +/// [`Display`]: ../fmt/trait.Display.html +/// [`Debug`]: ../fmt/trait.Debug.html +/// [`cause`]: trait.Error.html#method.cause #[stable(feature = "rust1", since = "1.0.0")] pub trait Error: Debug + Display { - /// A short description of the error. + /// **This method is soft-deprecated.** /// - /// The description should only be used for a simple message. - /// It should not contain newlines or sentence-ending punctuation, - /// to facilitate embedding in larger user-facing strings. - /// For showing formatted error messages with more information see - /// [`Display`]. + /// 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 /// /// ``` - /// use std::error::Error; - /// /// match "xc".parse::<u32>() { /// Err(e) => { - /// println!("Error: {}", e.description()); + /// // Print `e` itself, not `e.description()`. + /// println!("Error: {}", e); /// } /// _ => println!("No error"), /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn description(&self) -> &str; + fn description(&self) -> &str { + "description() is deprecated; use Display" + } /// The lower-level cause of this error, if any. /// @@ -151,7 +138,7 @@ pub trait Error: Debug + Display { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn cause(&self) -> Option<&Error> { None } + fn cause(&self) -> Option<&dyn Error> { None } /// Get the `TypeId` of `self` #[doc(hidden)] @@ -164,22 +151,22 @@ pub trait Error: Debug + Display { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> { - fn from(err: E) -> Box<Error + 'a> { +impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> { + fn from(err: E) -> Box<dyn Error + 'a> { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<Error + Send + Sync + 'a> { - fn from(err: E) -> Box<Error + Send + Sync + 'a> { +impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> { + fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] -impl From<String> for Box<Error + Send + Sync> { - fn from(err: String) -> Box<Error + Send + Sync> { +impl From<String> for Box<dyn Error + Send + Sync> { + fn from(err: String) -> Box<dyn Error + Send + Sync> { #[derive(Debug)] struct StringError(String); @@ -198,38 +185,38 @@ impl From<String> for Box<Error + Send + Sync> { } #[stable(feature = "string_box_error", since = "1.6.0")] -impl From<String> for Box<Error> { - fn from(str_err: String) -> Box<Error> { - let err1: Box<Error + Send + Sync> = From::from(str_err); - let err2: Box<Error> = err1; +impl From<String> for Box<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 } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> { - fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> { +impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> { + fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> { From::from(String::from(err)) } } #[stable(feature = "string_box_error", since = "1.6.0")] -impl<'a> From<&'a str> for Box<Error> { - fn from(err: &'a str) -> Box<Error> { +impl<'a> From<&'a str> for Box<dyn Error> { + fn from(err: &'a str) -> Box<dyn Error> { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a, 'b> From<Cow<'b, str>> for Box<Error + Send + Sync + 'a> { - fn from(err: Cow<'b, str>) -> Box<Error + Send + Sync + 'a> { +impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> { + fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a> From<Cow<'a, str>> for Box<Error> { - fn from(err: Cow<'a, str>) -> Box<Error> { +impl<'a> From<Cow<'a, str>> for Box<dyn Error> { + fn from(err: Cow<'a, str>) -> Box<dyn Error> { From::from(String::from(err)) } } @@ -242,18 +229,27 @@ impl Error for ! { #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] -impl Error for allocator::AllocErr { +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 { - allocator::AllocErr::description(self) + "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 allocator::CannotReallocInPlace { +impl Error for CannotReallocInPlace { fn description(&self) -> &str { - allocator::CannotReallocInPlace::description(self) + CannotReallocInPlace::description(self) } } @@ -331,7 +327,7 @@ impl<T: Error> Error for Box<T> { Error::description(&**self) } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { Error::cause(&**self) } } @@ -371,16 +367,8 @@ impl Error for char::ParseCharError { } } -#[unstable(feature = "try_from", issue = "33417")] -impl Error for convert::Infallible { - fn description(&self) -> &str { - match *self { - } - } -} - // copied from any.rs -impl Error + 'static { +impl dyn Error + 'static { /// Returns true if the boxed type is the same as `T` #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] @@ -402,7 +390,7 @@ impl Error + 'static { pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { if self.is::<T>() { unsafe { - Some(&*(self as *const Error as *const T)) + Some(&*(self as *const dyn Error as *const T)) } } else { None @@ -416,7 +404,7 @@ impl Error + 'static { pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { if self.is::<T>() { unsafe { - Some(&mut *(self as *mut Error as *mut T)) + Some(&mut *(self as *mut dyn Error as *mut T)) } } else { None @@ -424,60 +412,60 @@ impl Error + 'static { } } -impl Error + 'static + Send { +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<T: Error + 'static>(&self) -> bool { - <Error + 'static>::is::<T>(self) + <dyn Error + 'static>::is::<T>(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { - <Error + 'static>::downcast_ref::<T>(self) + <dyn Error + 'static>::downcast_ref::<T>(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { - <Error + 'static>::downcast_mut::<T>(self) + <dyn Error + 'static>::downcast_mut::<T>(self) } } -impl Error + 'static + Send + Sync { +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<T: Error + 'static>(&self) -> bool { - <Error + 'static>::is::<T>(self) + <dyn Error + 'static>::is::<T>(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { - <Error + 'static>::downcast_ref::<T>(self) + <dyn Error + 'static>::downcast_ref::<T>(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { - <Error + 'static>::downcast_mut::<T>(self) + <dyn Error + 'static>::downcast_mut::<T>(self) } } -impl Error { +impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] /// Attempt to downcast the box to a concrete type. - pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> { + pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> { if self.is::<T>() { unsafe { - let raw: *mut Error = Box::into_raw(self); + let raw: *mut dyn Error = Box::into_raw(self); Ok(Box::from_raw(raw as *mut T)) } } else { @@ -486,30 +474,30 @@ impl Error { } } -impl Error + Send { +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<T: Error + 'static>(self: Box<Self>) - -> Result<Box<T>, Box<Error + Send>> { - let err: Box<Error> = self; - <Error>::downcast(err).map_err(|s| unsafe { + -> 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<Error>, Box<Error + Send>>(s) + transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s) }) } } -impl Error + Send + Sync { +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<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> { - let err: Box<Error> = self; - <Error>::downcast(err).map_err(|s| unsafe { + let err: Box<dyn Error> = self; + <dyn Error>::downcast(err).map_err(|s| unsafe { // reapply the Send+Sync marker - transmute::<Box<Error>, Box<Error + Send + Sync>>(s) + transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s) }) } } @@ -545,13 +533,13 @@ mod tests { #[test] fn downcasting() { let mut a = A; - let a = &mut a as &mut (Error + 'static); + let a = &mut a as &mut (dyn Error + 'static); assert_eq!(a.downcast_ref::<A>(), Some(&A)); assert_eq!(a.downcast_ref::<B>(), None); assert_eq!(a.downcast_mut::<A>(), Some(&mut A)); assert_eq!(a.downcast_mut::<B>(), None); - let a: Box<Error> = Box::new(A); + let a: Box<dyn Error> = Box::new(A); match a.downcast::<B>() { Ok(..) => panic!("expected error"), Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A), |
