diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-03-31 16:01:03 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-03-31 16:12:48 -0700 |
| commit | ac77392f8ab1c201b0c927f6a2d30b632b95acda (patch) | |
| tree | f5c43d1b5cfdc7ce32e2c741c45c7e170e28c9cf | |
| parent | 80bf31dd514055177b22c3dc66836d39eb5b1648 (diff) | |
| download | rust-ac77392f8ab1c201b0c927f6a2d30b632b95acda.tar.gz rust-ac77392f8ab1c201b0c927f6a2d30b632b95acda.zip | |
std: Stabilize last bits of io::Error
This commit stabilizes a few remaining bits of the `io::Error` type: * The `Error::new` method is now stable. The last `detail` parameter was removed and the second `desc` parameter was generalized to `E: Into<Box<Error>>` to allow creating an I/O error from any form of error. Currently there is no form of downcasting, but this will be added in time. * An implementation of `From<&str> for Box<Error>` was added to liballoc to allow construction of errors from raw strings. * The `Error::raw_os_error` method was stabilized as-is. * Trait impls for `Clone`, `Eq`, and `PartialEq` were removed from `Error` as it is not possible to use them with trait objects. This is a breaking change due to the modification of the `new` method as well as the removal of the trait implementations for the `Error` type. [breaking-change]
| -rw-r--r-- | src/liballoc/boxed.rs | 46 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 1 | ||||
| -rw-r--r-- | src/librbml/lib.rs | 14 | ||||
| -rw-r--r-- | src/librustc_back/fs.rs | 4 | ||||
| -rw-r--r-- | src/librustc_back/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc_back/target/apple_ios_base.rs | 5 | ||||
| -rw-r--r-- | src/librustc_back/tempdir.rs | 3 | ||||
| -rw-r--r-- | src/librustc_driver/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc_driver/pretty.rs | 4 | ||||
| -rw-r--r-- | src/libstd/ffi/c_str.rs | 2 | ||||
| -rw-r--r-- | src/libstd/fs/mod.rs | 3 | ||||
| -rw-r--r-- | src/libstd/fs/tempdir.rs | 3 | ||||
| -rw-r--r-- | src/libstd/io/buffered.rs | 2 | ||||
| -rw-r--r-- | src/libstd/io/cursor.rs | 3 | ||||
| -rw-r--r-- | src/libstd/io/error.rs | 89 | ||||
| -rw-r--r-- | src/libstd/io/impls.rs | 2 | ||||
| -rw-r--r-- | src/libstd/io/mod.rs | 7 | ||||
| -rw-r--r-- | src/libstd/net/addr.rs | 2 | ||||
| -rw-r--r-- | src/libstd/net/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/net/udp.rs | 2 | ||||
| -rw-r--r-- | src/libstd/process.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/common/net2.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sys/unix/net.rs | 3 |
23 files changed, 109 insertions, 96 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f9bd0ab2f1e..37315b2e72f 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -56,8 +56,10 @@ use core::fmt; use core::hash::{self, Hash}; use core::mem; use core::ops::{Deref, DerefMut}; -use core::ptr::Unique; -use core::raw::TraitObject; +use core::ptr::{self, Unique}; +use core::raw::{TraitObject, Slice}; + +use heap; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. @@ -327,3 +329,43 @@ impl<'a, E: Error + 'a> FromError<E> for Box<Error + 'a> { Box::new(err) } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + 'a> From<E> for Box<Error + Send + 'a> { + fn from(err: E) -> Box<Error + Send + 'a> { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> { + fn from(err: &'b str) -> Box<Error + Send + 'a> { + #[derive(Debug)] + struct StringError(Box<str>); + impl Error for StringError { + fn description(&self) -> &str { &self.0 } + } + impl fmt::Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } + } + + // Unfortunately `String` is located in libcollections, so we construct + // a `Box<str>` manually here. + unsafe { + let alloc = if err.len() == 0 { + 0 as *mut u8 + } else { + let ptr = heap::allocate(err.len(), 1); + if ptr.is_null() { ::oom(); } + ptr as *mut u8 + }; + ptr::copy(err.as_bytes().as_ptr(), alloc, err.len()); + Box::new(StringError(mem::transmute(Slice { + data: alloc, + len: err.len(), + }))) + } + } +} diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b92dfa9117e..a880ba5cfe4 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -78,6 +78,7 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(core)] #![feature(unique)] +#![feature(convert)] #![cfg_attr(test, feature(test, alloc, rustc_private))] #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")), feature(libc))] diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 092cd780ec7..878ef04942a 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -862,8 +862,8 @@ pub mod writer { } else if 0x100 <= n && n < NUM_TAGS { w.write_all(&[0xf0 | (n >> 8) as u8, n as u8]) } else { - Err(io::Error::new(io::ErrorKind::Other, "invalid tag", - Some(n.to_string()))) + Err(io::Error::new(io::ErrorKind::Other, + &format!("invalid tag: {}", n)[..])) } } @@ -876,7 +876,7 @@ pub mod writer { 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]), _ => Err(io::Error::new(io::ErrorKind::Other, - "isize too big", Some(n.to_string()))) + &format!("isize too big: {}", n)[..])) } } @@ -885,8 +885,8 @@ pub mod writer { if n < 0x4000 { return write_sized_vuint(w, n, 2); } if n < 0x200000 { return write_sized_vuint(w, n, 3); } if n < 0x10000000 { return write_sized_vuint(w, n, 4); } - Err(io::Error::new(io::ErrorKind::Other, "isize too big", - Some(n.to_string()))) + Err(io::Error::new(io::ErrorKind::Other, + &format!("isize too big: {}", n)[..])) } impl<'a> Encoder<'a> { @@ -1077,8 +1077,8 @@ pub mod writer { self.wr_tagged_raw_u32(EsSub32 as usize, v) } else { Err(io::Error::new(io::ErrorKind::Other, - "length or variant id too big", - Some(v.to_string()))) + &format!("length or variant id too big: {}", + v)[..])) } } diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index 6d8891dd4fe..214cec4e292 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -20,9 +20,7 @@ pub fn realpath(original: &Path) -> io::Result<PathBuf> { let old = old_path::Path::new(original.to_str().unwrap()); match old_realpath(&old) { Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())), - Err(e) => Err(io::Error::new(io::ErrorKind::Other, - "realpath error", - Some(e.to_string()))) + Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)) } } diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index fe457841e91..6a5a5201c10 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -36,7 +36,6 @@ #![feature(collections)] #![feature(core)] #![feature(old_fs)] -#![feature(io)] #![feature(old_io)] #![feature(old_path)] #![feature(os)] diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 2fbbe7d1f7c..42cbdd7577d 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -47,9 +47,10 @@ pub fn get_sdk_root(sdk_name: &str) -> String { Ok(String::from_utf8(output.stdout).unwrap()) } else { let error = String::from_utf8(output.stderr); + let error = format!("process exit with error: {}", + error.unwrap()); Err(io::Error::new(io::ErrorKind::Other, - "process exit with error", - error.ok())) + &error[..])) } }); diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs index d4503ae7fc9..3bf9827411a 100644 --- a/src/librustc_back/tempdir.rs +++ b/src/librustc_back/tempdir.rs @@ -67,8 +67,7 @@ impl TempDir { } Err(Error::new(ErrorKind::AlreadyExists, - "too many temporary directories already exist", - None)) + "too many temporary directories already exist")) } /// Attempts to make a temporary directory inside of `env::temp_dir()` whose diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 456d5f7a60a..f087a2c742b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -35,7 +35,6 @@ #![feature(unsafe_destructor)] #![feature(staged_api)] #![feature(exit_status)] -#![feature(io)] #![feature(set_stdio)] #![feature(unicode)] #![feature(convert)] diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 9e693a64ef0..fe55ca3b73b 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -699,8 +699,8 @@ fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>, fn expand_err_details(r: io::Result<()>) -> io::Result<()> { r.map_err(|ioerr| { - io::Error::new(io::ErrorKind::Other, "graphviz::render failed", - Some(ioerr.to_string())) + io::Error::new(io::ErrorKind::Other, + &format!("graphviz::render failed: {}", ioerr)[..]) }) } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a00f7708025..622e6b54f5e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -301,7 +301,7 @@ impl fmt::Display for NulError { impl FromError<NulError> for io::Error { fn from_error(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, - "data provided contains a nul byte", None) + "data provided contains a nul byte") } } diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs index a3128ef0f8d..a5186ad9a98 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs/mod.rs @@ -575,8 +575,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { let to = to.as_ref(); if !from.is_file() { return Err(Error::new(ErrorKind::InvalidInput, - "the source path is not an existing file", - None)) + "the source path is not an existing file")) } let mut reader = try!(File::open(from)); diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs index 8cc1dde98a0..24f285e424e 100644 --- a/src/libstd/fs/tempdir.rs +++ b/src/libstd/fs/tempdir.rs @@ -73,8 +73,7 @@ impl TempDir { } Err(Error::new(ErrorKind::AlreadyExists, - "too many temporary directories already exist", - None)) + "too many temporary directories already exist")) } /// Attempts to make a temporary directory inside of `env::temp_dir()` whose diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 8eea06bf6b0..9abc30b7da8 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -165,7 +165,7 @@ impl<W: Write> BufWriter<W> { match self.inner.as_mut().unwrap().write(&self.buf[written..]) { Ok(0) => { ret = Err(Error::new(ErrorKind::WriteZero, - "failed to write the buffered data", None)); + "failed to write the buffered data")); break; } Ok(n) => written += n, diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index d8e403376bd..87bd8540931 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -75,8 +75,7 @@ macro_rules! seek { if pos < 0 { Err(Error::new(ErrorKind::InvalidInput, - "invalid seek to a negative position", - None)) + "invalid seek to a negative position")) } else { self.pos = pos as u64; Ok(self.pos) diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index f445ace081e..b84dcb8fb62 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -9,12 +9,12 @@ // except according to those terms. use boxed::Box; -use clone::Clone; +use convert::Into; use error; use fmt; +use marker::Send; use option::Option::{self, Some, None}; use result; -use string::String; use sys; /// A type for results generated by I/O related functions where the `Err` type @@ -31,23 +31,22 @@ pub type Result<T> = result::Result<T, Error>; /// Errors mostly originate from the underlying OS, but custom instances of /// `Error` can be created with crafted error messages and a particular value of /// `ErrorKind`. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Error { repr: Repr, } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] enum Repr { Os(i32), Custom(Box<Custom>), } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] struct Custom { kind: ErrorKind, - desc: &'static str, - detail: Option<String> + error: Box<error::Error+Send>, } /// A list specifying general categories of I/O error. @@ -125,18 +124,34 @@ pub enum ErrorKind { } impl Error { - /// Creates a new custom error from a specified kind/description/detail. - #[unstable(feature = "io", reason = "the exact makeup of an Error may - change to include `Box<Error>` for \ - example")] - pub fn new(kind: ErrorKind, - description: &'static str, - detail: Option<String>) -> Error { + /// Creates a new I/O error from a known kind of error as well as an + /// arbitrary error payload. + /// + /// 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. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// // errors can be created from strings + /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new<E>(kind: ErrorKind, error: E) -> Error + where E: Into<Box<error::Error+Send>> + { Error { repr: Repr::Custom(Box::new(Custom { kind: kind, - desc: description, - detail: detail, + error: error.into(), })) } } @@ -162,8 +177,7 @@ impl Error { /// /// If this `Error` was constructed via `last_os_error` then this function /// will return `Some`, otherwise it will return `None`. - #[unstable(feature = "io", reason = "function was just added and the return \ - type may become an abstract OS error")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn raw_os_error(&self) -> Option<i32> { match self.repr { Repr::Os(i) => Some(i), @@ -179,27 +193,6 @@ impl Error { Repr::Custom(ref c) => c.kind, } } - - /// Returns a short description for this error message - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the Error trait's description \ - method instead")] - pub fn description(&self) -> &str { - match self.repr { - Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, - } - } - - /// Returns a detailed error message for this error (if one is available) - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the to_string() method instead")] - pub fn detail(&self) -> Option<String> { - match self.repr { - Repr::Os(code) => Some(sys::os::error_string(code)), - Repr::Custom(ref s) => s.detail.clone(), - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -210,21 +203,7 @@ impl fmt::Display for Error { let detail = sys::os::error_string(code); write!(fmt, "{} (os error {})", detail, code) } - Repr::Custom(ref c) => { - match **c { - Custom { - kind: ErrorKind::Other, - desc: "unknown error", - detail: Some(ref detail) - } => { - write!(fmt, "{}", detail) - } - Custom { detail: None, desc, .. } => - write!(fmt, "{}", desc), - Custom { detail: Some(ref detail), desc, .. } => - write!(fmt, "{} ({})", desc, detail) - } - } + Repr::Custom(ref c) => c.error.fmt(fmt), } } } @@ -234,7 +213,7 @@ impl error::Error for Error { fn description(&self) -> &str { match self.repr { Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, + Repr::Custom(ref c) => c.error.description(), } } } diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 52daba36213..67bc45d3b62 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -180,7 +180,7 @@ impl<'a> Write for &'a mut [u8] { if try!(self.write(data)) == data.len() { Ok(()) } else { - Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer", None)) + Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 830a88bb6c9..91ea7ab4df6 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -83,7 +83,7 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize> if str::from_utf8(&g.s[g.len..]).is_err() { ret.and_then(|_| { Err(Error::new(ErrorKind::InvalidInput, - "stream did not contain valid UTF-8", None)) + "stream did not contain valid UTF-8")) }) } else { g.len = g.s.len(); @@ -359,8 +359,7 @@ pub trait Write { while buf.len() > 0 { match self.write(buf) { Ok(0) => return Err(Error::new(ErrorKind::WriteZero, - "failed to write whole buffer", - None)), + "failed to write whole buffer")), Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), @@ -780,7 +779,7 @@ pub struct Chars<R> { /// An enumeration of possible errors that can be generated from the `Chars` /// adapter. -#[derive(PartialEq, Clone, Debug)] +#[derive(Debug)] #[unstable(feature = "io", reason = "awaiting stability of Read::chars")] pub enum CharsError { /// Variant representing that the underlying stream was read successfully diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index a08b33b342b..eb6cb441606 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -435,7 +435,7 @@ impl ToSocketAddrs for str { match $e { Some(r) => r, None => return Err(io::Error::new(io::ErrorKind::InvalidInput, - $msg, None)), + $msg)), } ) } diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index ee57300765e..a152b98822a 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -72,7 +72,7 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T> } Err(last_err.unwrap_or_else(|| { Error::new(ErrorKind::InvalidInput, - "could not resolve to any addresses", None) + "could not resolve to any addresses") })) } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 81151114962..511c2e3f8b2 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -76,7 +76,7 @@ impl UdpSocket { match try!(addr.to_socket_addrs()).next() { Some(addr) => self.0.send_to(buf, &addr), None => Err(Error::new(ErrorKind::InvalidInput, - "no addresses to send data to", None)), + "no addresses to send data to")), } } diff --git a/src/libstd/process.rs b/src/libstd/process.rs index b4bd513e8f0..7921296dabf 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -461,7 +461,6 @@ impl Child { return Err(Error::new( ErrorKind::InvalidInput, "invalid argument: can't kill an exited process", - None )) } diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index a8ee40639e3..b4903096cce 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -75,7 +75,7 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage, }))) } _ => { - Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None)) + Err(Error::new(ErrorKind::InvalidInput, "invalid argument")) } } } @@ -158,8 +158,7 @@ pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> { match from_utf8(data.to_bytes()) { Ok(name) => Ok(name.to_string()), Err(_) => Err(io::Error::new(io::ErrorKind::Other, - "failed to lookup address information", - Some("invalid host name".to_string()))) + "failed to lookup address information")) } } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index b22fa33e562..205f30810b5 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -35,7 +35,8 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { .to_string() }; Err(io::Error::new(io::ErrorKind::Other, - "failed to lookup address information", Some(detail))) + &format!("failed to lookup address information: {}", + detail)[..])) } impl Socket { |
