Skip to content

Commit 50b3ecf

Browse files
committed
rollup merge of #23919: alexcrichton/stabilize-io-error
Conflicts: src/libstd/fs/tempdir.rs src/libstd/io/error.rs
2 parents 85e997a + ac77392 commit 50b3ecf

File tree

22 files changed

+108
-72
lines changed

22 files changed

+108
-72
lines changed

src/liballoc/boxed.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ use core::fmt;
5656
use core::hash::{self, Hash};
5757
use core::mem;
5858
use core::ops::{Deref, DerefMut};
59-
use core::ptr::Unique;
60-
use core::raw::TraitObject;
59+
use core::ptr::{self, Unique};
60+
use core::raw::{TraitObject, Slice};
61+
62+
use heap;
6163

6264
/// A value that represents the heap. This is the default place that the `box`
6365
/// keyword allocates into when no place is supplied.
@@ -313,3 +315,43 @@ impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
313315
Box::new(err)
314316
}
315317
}
318+
319+
#[stable(feature = "rust1", since = "1.0.0")]
320+
impl<'a, E: Error + Send + 'a> From<E> for Box<Error + Send + 'a> {
321+
fn from(err: E) -> Box<Error + Send + 'a> {
322+
Box::new(err)
323+
}
324+
}
325+
326+
#[stable(feature = "rust1", since = "1.0.0")]
327+
impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> {
328+
fn from(err: &'b str) -> Box<Error + Send + 'a> {
329+
#[derive(Debug)]
330+
struct StringError(Box<str>);
331+
impl Error for StringError {
332+
fn description(&self) -> &str { &self.0 }
333+
}
334+
impl fmt::Display for StringError {
335+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336+
self.0.fmt(f)
337+
}
338+
}
339+
340+
// Unfortunately `String` is located in libcollections, so we construct
341+
// a `Box<str>` manually here.
342+
unsafe {
343+
let alloc = if err.len() == 0 {
344+
0 as *mut u8
345+
} else {
346+
let ptr = heap::allocate(err.len(), 1);
347+
if ptr.is_null() { ::oom(); }
348+
ptr as *mut u8
349+
};
350+
ptr::copy(err.as_bytes().as_ptr(), alloc, err.len());
351+
Box::new(StringError(mem::transmute(Slice {
352+
data: alloc,
353+
len: err.len(),
354+
})))
355+
}
356+
}
357+
}

src/liballoc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#![feature(unsafe_no_drop_flag, filling_drop)]
7979
#![feature(core)]
8080
#![feature(unique)]
81+
#![feature(convert)]
8182
#![cfg_attr(test, feature(test, alloc, rustc_private))]
8283
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
8384
feature(libc))]

src/librbml/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -862,8 +862,8 @@ pub mod writer {
862862
} else if 0x100 <= n && n < NUM_TAGS {
863863
w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
864864
} else {
865-
Err(io::Error::new(io::ErrorKind::Other, "invalid tag",
866-
Some(n.to_string())))
865+
Err(io::Error::new(io::ErrorKind::Other,
866+
&format!("invalid tag: {}", n)[..]))
867867
}
868868
}
869869

@@ -876,7 +876,7 @@ pub mod writer {
876876
4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
877877
(n >> 8) as u8, n as u8]),
878878
_ => Err(io::Error::new(io::ErrorKind::Other,
879-
"isize too big", Some(n.to_string())))
879+
&format!("isize too big: {}", n)[..]))
880880
}
881881
}
882882

@@ -885,8 +885,8 @@ pub mod writer {
885885
if n < 0x4000 { return write_sized_vuint(w, n, 2); }
886886
if n < 0x200000 { return write_sized_vuint(w, n, 3); }
887887
if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
888-
Err(io::Error::new(io::ErrorKind::Other, "isize too big",
889-
Some(n.to_string())))
888+
Err(io::Error::new(io::ErrorKind::Other,
889+
&format!("isize too big: {}", n)[..]))
890890
}
891891

892892
impl<'a> Encoder<'a> {
@@ -1077,8 +1077,8 @@ pub mod writer {
10771077
self.wr_tagged_raw_u32(EsSub32 as usize, v)
10781078
} else {
10791079
Err(io::Error::new(io::ErrorKind::Other,
1080-
"length or variant id too big",
1081-
Some(v.to_string())))
1080+
&format!("length or variant id too big: {}",
1081+
v)[..]))
10821082
}
10831083
}
10841084

src/librustc_back/fs.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ pub fn realpath(original: &Path) -> io::Result<PathBuf> {
2121
let old = old_path::Path::new(original.to_str().unwrap());
2222
match old_realpath(&old) {
2323
Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())),
24-
Err(e) => Err(io::Error::new(io::ErrorKind::Other,
25-
"realpath error",
26-
Some(e.to_string())))
24+
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
2725
}
2826
}
2927

src/librustc_back/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
#![feature(collections)]
3737
#![feature(core)]
3838
#![feature(old_fs)]
39-
#![feature(io)]
4039
#![feature(old_io)]
4140
#![feature(old_path)]
4241
#![feature(rustc_private)]

src/librustc_back/target/apple_ios_base.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ pub fn get_sdk_root(sdk_name: &str) -> String {
4747
Ok(String::from_utf8(output.stdout).unwrap())
4848
} else {
4949
let error = String::from_utf8(output.stderr);
50+
let error = format!("process exit with error: {}",
51+
error.unwrap());
5052
Err(io::Error::new(io::ErrorKind::Other,
51-
"process exit with error",
52-
error.ok()))
53+
&error[..]))
5354
}
5455
});
5556

src/librustc_back/tempdir.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ impl TempDir {
6767
}
6868

6969
Err(Error::new(ErrorKind::AlreadyExists,
70-
"too many temporary directories already exist",
71-
None))
70+
"too many temporary directories already exist"))
7271
}
7372

7473
/// Attempts to make a temporary directory inside of `env::temp_dir()` whose

src/librustc_driver/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
#![feature(unsafe_destructor)]
3535
#![feature(staged_api)]
3636
#![feature(exit_status)]
37-
#![feature(io)]
3837
#![feature(set_stdio)]
3938
#![feature(unicode)]
4039

src/librustc_driver/pretty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,8 +699,8 @@ fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>,
699699

700700
fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
701701
r.map_err(|ioerr| {
702-
io::Error::new(io::ErrorKind::Other, "graphviz::render failed",
703-
Some(ioerr.to_string()))
702+
io::Error::new(io::ErrorKind::Other,
703+
&format!("graphviz::render failed: {}", ioerr)[..])
704704
})
705705
}
706706
}

src/libstd/ffi/c_str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ impl fmt::Display for NulError {
241241
impl From<NulError> for io::Error {
242242
fn from(_: NulError) -> io::Error {
243243
io::Error::new(io::ErrorKind::InvalidInput,
244-
"data provided contains a nul byte", None)
244+
"data provided contains a nul byte")
245245
}
246246
}
247247

src/libstd/fs.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
576576
let to = to.as_ref();
577577
if !from.is_file() {
578578
return Err(Error::new(ErrorKind::InvalidInput,
579-
"the source path is not an existing file",
580-
None))
579+
"the source path is not an existing file"))
581580
}
582581

583582
let mut reader = try!(File::open(from));

src/libstd/io/buffered.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<W: Write> BufWriter<W> {
165165
match self.inner.as_mut().unwrap().write(&self.buf[written..]) {
166166
Ok(0) => {
167167
ret = Err(Error::new(ErrorKind::WriteZero,
168-
"failed to write the buffered data", None));
168+
"failed to write the buffered data"));
169169
break;
170170
}
171171
Ok(n) => written += n,

src/libstd/io/cursor.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ macro_rules! seek {
7575

7676
if pos < 0 {
7777
Err(Error::new(ErrorKind::InvalidInput,
78-
"invalid seek to a negative position",
79-
None))
78+
"invalid seek to a negative position"))
8079
} else {
8180
self.pos = pos as u64;
8281
Ok(self.pos)

src/libstd/io/error.rs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
// except according to those terms.
1010

1111
use boxed::Box;
12+
use convert::Into;
1213
use error;
1314
use fmt;
15+
use marker::Send;
1416
use option::Option::{self, Some, None};
1517
use result;
16-
use string::String;
1718
use sys;
1819

1920
/// A type for results generated by I/O related functions where the `Err` type
@@ -30,23 +31,22 @@ pub type Result<T> = result::Result<T, Error>;
3031
/// Errors mostly originate from the underlying OS, but custom instances of
3132
/// `Error` can be created with crafted error messages and a particular value of
3233
/// `ErrorKind`.
33-
#[derive(PartialEq, Eq, Clone, Debug)]
34+
#[derive(Debug)]
3435
#[stable(feature = "rust1", since = "1.0.0")]
3536
pub struct Error {
3637
repr: Repr,
3738
}
3839

39-
#[derive(PartialEq, Eq, Clone, Debug)]
40+
#[derive(Debug)]
4041
enum Repr {
4142
Os(i32),
4243
Custom(Box<Custom>),
4344
}
4445

45-
#[derive(PartialEq, Eq, Clone, Debug)]
46+
#[derive(Debug)]
4647
struct Custom {
4748
kind: ErrorKind,
48-
desc: &'static str,
49-
detail: Option<String>
49+
error: Box<error::Error+Send>,
5050
}
5151

5252
/// A list specifying general categories of I/O error.
@@ -124,18 +124,34 @@ pub enum ErrorKind {
124124
}
125125

126126
impl Error {
127-
/// Creates a new custom error from a specified kind/description/detail.
128-
#[unstable(feature = "io", reason = "the exact makeup of an Error may
129-
change to include `Box<Error>` for \
130-
example")]
131-
pub fn new(kind: ErrorKind,
132-
description: &'static str,
133-
detail: Option<String>) -> Error {
127+
/// Creates a new I/O error from a known kind of error as well as an
128+
/// arbitrary error payload.
129+
///
130+
/// This function is used to generically create I/O errors which do not
131+
/// originate from the OS itself. The `error` argument is an arbitrary
132+
/// payload which will be contained in this `Error`. Accessors as well as
133+
/// downcasting will soon be added to this type as well to access the custom
134+
/// information.
135+
///
136+
/// # Examples
137+
///
138+
/// ```
139+
/// use std::io::{Error, ErrorKind};
140+
///
141+
/// // errors can be created from strings
142+
/// let custom_error = Error::new(ErrorKind::Other, "oh no!");
143+
///
144+
/// // errors can also be created from other errors
145+
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
146+
/// ```
147+
#[stable(feature = "rust1", since = "1.0.0")]
148+
pub fn new<E>(kind: ErrorKind, error: E) -> Error
149+
where E: Into<Box<error::Error+Send>>
150+
{
134151
Error {
135152
repr: Repr::Custom(Box::new(Custom {
136153
kind: kind,
137-
desc: description,
138-
detail: detail,
154+
error: error.into(),
139155
}))
140156
}
141157
}
@@ -161,8 +177,7 @@ impl Error {
161177
///
162178
/// If this `Error` was constructed via `last_os_error` then this function
163179
/// will return `Some`, otherwise it will return `None`.
164-
#[unstable(feature = "io", reason = "function was just added and the return \
165-
type may become an abstract OS error")]
180+
#[stable(feature = "rust1", since = "1.0.0")]
166181
pub fn raw_os_error(&self) -> Option<i32> {
167182
match self.repr {
168183
Repr::Os(i) => Some(i),
@@ -188,21 +203,7 @@ impl fmt::Display for Error {
188203
let detail = sys::os::error_string(code);
189204
write!(fmt, "{} (os error {})", detail, code)
190205
}
191-
Repr::Custom(ref c) => {
192-
match **c {
193-
Custom {
194-
kind: ErrorKind::Other,
195-
desc: "unknown error",
196-
detail: Some(ref detail)
197-
} => {
198-
write!(fmt, "{}", detail)
199-
}
200-
Custom { detail: None, desc, .. } =>
201-
write!(fmt, "{}", desc),
202-
Custom { detail: Some(ref detail), desc, .. } =>
203-
write!(fmt, "{} ({})", desc, detail)
204-
}
205-
}
206+
Repr::Custom(ref c) => c.error.fmt(fmt),
206207
}
207208
}
208209
}
@@ -212,7 +213,7 @@ impl error::Error for Error {
212213
fn description(&self) -> &str {
213214
match self.repr {
214215
Repr::Os(..) => "os error",
215-
Repr::Custom(ref c) => c.desc,
216+
Repr::Custom(ref c) => c.error.description(),
216217
}
217218
}
218219
}

src/libstd/io/impls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ impl<'a> Write for &'a mut [u8] {
180180
if try!(self.write(data)) == data.len() {
181181
Ok(())
182182
} else {
183-
Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer", None))
183+
Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"))
184184
}
185185
}
186186

src/libstd/io/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
8383
if str::from_utf8(&g.s[g.len..]).is_err() {
8484
ret.and_then(|_| {
8585
Err(Error::new(ErrorKind::InvalidInput,
86-
"stream did not contain valid UTF-8", None))
86+
"stream did not contain valid UTF-8"))
8787
})
8888
} else {
8989
g.len = g.s.len();
@@ -359,8 +359,7 @@ pub trait Write {
359359
while buf.len() > 0 {
360360
match self.write(buf) {
361361
Ok(0) => return Err(Error::new(ErrorKind::WriteZero,
362-
"failed to write whole buffer",
363-
None)),
362+
"failed to write whole buffer")),
364363
Ok(n) => buf = &buf[n..],
365364
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
366365
Err(e) => return Err(e),
@@ -782,7 +781,7 @@ pub struct Chars<R> {
782781

783782
/// An enumeration of possible errors that can be generated from the `Chars`
784783
/// adapter.
785-
#[derive(PartialEq, Clone, Debug)]
784+
#[derive(Debug)]
786785
#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
787786
pub enum CharsError {
788787
/// Variant representing that the underlying stream was read successfully

src/libstd/net/addr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ impl ToSocketAddrs for str {
435435
match $e {
436436
Some(r) => r,
437437
None => return Err(io::Error::new(io::ErrorKind::InvalidInput,
438-
$msg, None)),
438+
$msg)),
439439
}
440440
)
441441
}

src/libstd/net/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
7272
}
7373
Err(last_err.unwrap_or_else(|| {
7474
Error::new(ErrorKind::InvalidInput,
75-
"could not resolve to any addresses", None)
75+
"could not resolve to any addresses")
7676
}))
7777
}
7878

src/libstd/net/udp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl UdpSocket {
7676
match try!(addr.to_socket_addrs()).next() {
7777
Some(addr) => self.0.send_to(buf, &addr),
7878
None => Err(Error::new(ErrorKind::InvalidInput,
79-
"no addresses to send data to", None)),
79+
"no addresses to send data to")),
8080
}
8181
}
8282

0 commit comments

Comments
 (0)