diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 97c5a29d308a1..85b957640fdab 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -129,9 +129,7 @@ impl Error { /// /// This function is used to generically create I/O errors which do not /// originate from the OS itself. The `error` argument is an arbitrary - /// payload which will be contained in this `Error`. Accessors as well as - /// downcasting will soon be added to this type as well to access the custom - /// information. + /// payload which will be contained in this `Error`. /// /// # Examples /// @@ -174,8 +172,9 @@ impl Error { /// Returns the OS error that this error represents (if any). /// - /// If this `Error` was constructed via `last_os_error` then this function - /// will return `Some`, otherwise it will return `None`. + /// If this `Error` was constructed via `last_os_error` or + /// `from_raw_os_error`, then this function will return `Some`, otherwise + /// it will return `None`. #[stable(feature = "rust1", since = "1.0.0")] pub fn raw_os_error(&self) -> Option { match self.repr { @@ -184,6 +183,46 @@ impl Error { } } + /// Returns a reference to the inner error wrapped by this error (if any). + /// + /// If this `Error` was constructed via `new` then this function will + /// return `Some`, otherwise it will return `None`. + #[unstable(feature = "io_error_inner", + reason = "recently added and requires UFCS to downcast")] + pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { + match self.repr { + Repr::Os(..) => None, + Repr::Custom(ref c) => Some(&*c.error), + } + } + + /// Returns a mutable reference to the inner error wrapped by this error + /// (if any). + /// + /// If this `Error` was constructed via `new` then this function will + /// return `Some`, otherwise it will return `None`. + #[unstable(feature = "io_error_inner", + reason = "recently added and requires UFCS to downcast")] + pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { + match self.repr { + Repr::Os(..) => None, + Repr::Custom(ref mut c) => Some(&mut *c.error), + } + } + + /// Consumes the `Error`, returning its inner error (if any). + /// + /// If this `Error` was constructed via `new` then this function will + /// return `Some`, otherwise it will return `None`. + #[unstable(feature = "io_error_inner", + reason = "recently added and requires UFCS to downcast")] + pub fn into_inner(self) -> Option> { + match self.repr { + Repr::Os(..) => None, + Repr::Custom(c) => Some(c.error) + } + } + /// Returns the corresponding `ErrorKind` for this error. #[stable(feature = "rust1", since = "1.0.0")] pub fn kind(&self) -> ErrorKind { @@ -215,9 +254,52 @@ impl error::Error for Error { Repr::Custom(ref c) => c.error.description(), } } + + fn cause(&self) -> Option<&error::Error> { + match self.repr { + Repr::Os(..) => None, + Repr::Custom(ref c) => c.error.cause(), + } + } } fn _assert_error_is_sync_send() { fn _is_sync_send() {} _is_sync_send::(); } + +#[cfg(test)] +mod test { + use prelude::v1::*; + use super::{Error, ErrorKind}; + use error; + use error::Error as error_Error; + use fmt; + + #[test] + fn test_downcasting() { + #[derive(Debug)] + struct TestError; + + impl fmt::Display for TestError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } + } + + impl error::Error for TestError { + fn description(&self) -> &str { + "asdf" + } + } + + // we have to call all of these UFCS style right now since method + // resolution won't implicitly drop the Send+Sync bounds + let mut err = Error::new(ErrorKind::Other, TestError); + assert!(error::Error::is::(err.get_ref().unwrap())); + assert_eq!("asdf", err.get_ref().unwrap().description()); + assert!(error::Error::is::(err.get_mut().unwrap())); + let extracted = err.into_inner().unwrap(); + error::Error::downcast::(extracted).unwrap(); + } +}