Skip to content

Commit 7f53b94

Browse files
committed
Auto merge of #23430 - alexcrichton:io-error, r=aturon
This commit stabilizes the `ErrorKind` enumeration which is consumed by and generated by the `io::Error` type. The purpose of this type is to serve as a cross-platform namespace to categorize errors into. Two specific issues are addressed as part of this stablization: * The naming of each variant was scrutinized and some were tweaked. An example is how `FileNotFound` was renamed to simply `NotFound`. These names should not show either a Unix or Windows bias and the set of names is intended to grow over time. For now the names will likely largely consist of those errors generated by the I/O APIs in the standard library. * The mapping of OS error codes onto kinds has been altered. Coalescing no longer occurs (multiple error codes become one kind). It is intended that each OS error code, if bound, corresponds to only one `ErrorKind`. The current set of error kinds was expanded slightly to include some networking errors. This commit also adds a `raw_os_error` function which returns an `Option<i32>` to extract the underlying raw error code from the `Error`. Closes #16666 [breaking-change]
2 parents 81e2396 + dedac5e commit 7f53b94

File tree

10 files changed

+83
-52
lines changed

10 files changed

+83
-52
lines changed

src/librustc_back/tempdir.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ impl TempDir {
6161
let path = tmpdir.join(&leaf);
6262
match fs::create_dir(&path) {
6363
Ok(_) => return Ok(TempDir { path: Some(path) }),
64-
Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
64+
Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
6565
Err(e) => return Err(e)
6666
}
6767
}
6868

69-
Err(Error::new(ErrorKind::PathAlreadyExists,
69+
Err(Error::new(ErrorKind::AlreadyExists,
7070
"too many temporary directories already exist",
7171
None))
7272
}

src/librustdoc/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#![feature(test)]
3636
#![feature(unicode)]
3737
#![feature(str_words)]
38-
#![feature(io)]
3938
#![feature(file_path)]
4039
#![feature(path_ext)]
4140
#![feature(path_relative_from)]

src/libserialize/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ Core encoding and decoding interfaces.
3131
#![feature(collections)]
3232
#![feature(core)]
3333
#![feature(int_uint)]
34-
#![feature(io)]
3534
#![feature(old_path)]
3635
#![feature(rustc_private)]
3736
#![feature(staged_api)]

src/libstd/fs/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ pub fn copy<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<u64> {
493493
let from = from.as_path();
494494
let to = to.as_path();
495495
if !from.is_file() {
496-
return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation,
496+
return Err(Error::new(ErrorKind::InvalidInput,
497497
"the source path is not an existing file",
498498
None))
499499
}
@@ -1134,7 +1134,7 @@ mod tests {
11341134
let dir = &tmpdir.join("mkdir_error_twice");
11351135
check!(fs::create_dir(dir));
11361136
let e = fs::create_dir(dir).err().unwrap();
1137-
assert_eq!(e.kind(), ErrorKind::PathAlreadyExists);
1137+
assert_eq!(e.kind(), ErrorKind::AlreadyExists);
11381138
}
11391139

11401140
#[test]

src/libstd/fs/tempdir.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ impl TempDir {
6868
let path = tmpdir.join(&leaf);
6969
match fs::create_dir(&path) {
7070
Ok(_) => return Ok(TempDir { path: Some(path) }),
71-
Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
71+
Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
7272
Err(e) => return Err(e)
7373
}
7474
}
7575

76-
Err(Error::new(ErrorKind::PathAlreadyExists,
76+
Err(Error::new(ErrorKind::AlreadyExists,
7777
"too many temporary directories already exist",
7878
None))
7979
}

src/libstd/io/error.rs

+58-21
Original file line numberDiff line numberDiff line change
@@ -51,53 +51,77 @@ struct Custom {
5151
}
5252

5353
/// A list specifying general categories of I/O error.
54+
///
55+
/// This list is intended to grow over time and it is not recommended to
56+
/// exhaustively match against it.
5457
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
55-
#[unstable(feature = "io",
56-
reason = "the interaction between OS error codes and how they map to \
57-
these names (as well as the names themselves) has not \
58-
been thoroughly thought out")]
58+
#[stable(feature = "rust1", since = "1.0.0")]
5959
pub enum ErrorKind {
60-
/// The file was not found.
61-
FileNotFound,
62-
/// The file permissions disallowed access to this file.
60+
/// An entity was not found, often a file.
61+
#[stable(feature = "rust1", since = "1.0.0")]
62+
NotFound,
63+
/// The operation lacked the necessary privileges to complete.
64+
#[stable(feature = "rust1", since = "1.0.0")]
6365
PermissionDenied,
6466
/// The connection was refused by the remote server.
67+
#[stable(feature = "rust1", since = "1.0.0")]
6568
ConnectionRefused,
6669
/// The connection was reset by the remote server.
70+
#[stable(feature = "rust1", since = "1.0.0")]
6771
ConnectionReset,
6872
/// The connection was aborted (terminated) by the remote server.
73+
#[stable(feature = "rust1", since = "1.0.0")]
6974
ConnectionAborted,
7075
/// The network operation failed because it was not connected yet.
76+
#[stable(feature = "rust1", since = "1.0.0")]
7177
NotConnected,
78+
/// A socket address could not be bound because the address is already in
79+
/// use elsewhere.
80+
#[stable(feature = "rust1", since = "1.0.0")]
81+
AddrInUse,
82+
/// A nonexistent interface was requested or the requested address was not
83+
/// local.
84+
#[stable(feature = "rust1", since = "1.0.0")]
85+
AddrNotAvailable,
7286
/// The operation failed because a pipe was closed.
87+
#[stable(feature = "rust1", since = "1.0.0")]
7388
BrokenPipe,
74-
/// A file already existed with that name.
75-
PathAlreadyExists,
76-
/// No file exists at that location.
77-
PathDoesntExist,
78-
/// The path did not specify the type of file that this operation required.
79-
/// For example, attempting to copy a directory with the `fs::copy()`
80-
/// operation will fail with this error.
81-
MismatchedFileTypeForOperation,
82-
/// The operation temporarily failed (for example, because a signal was
83-
/// received), and retrying may succeed.
84-
ResourceUnavailable,
85-
/// A parameter was incorrect in a way that caused an I/O error not part of
86-
/// this list.
89+
/// An entity already exists, often a file.
90+
#[stable(feature = "rust1", since = "1.0.0")]
91+
AlreadyExists,
92+
/// The operation needs to block to complete, but the blocking operation was
93+
/// requested to not occur.
94+
#[stable(feature = "rust1", since = "1.0.0")]
95+
WouldBlock,
96+
/// A parameter was incorrect.
97+
#[stable(feature = "rust1", since = "1.0.0")]
8798
InvalidInput,
8899
/// The I/O operation's timeout expired, causing it to be canceled.
100+
#[stable(feature = "rust1", since = "1.0.0")]
89101
TimedOut,
90102
/// An error returned when an operation could not be completed because a
91103
/// call to `write` returned `Ok(0)`.
92104
///
93105
/// This typically means that an operation could only succeed if it wrote a
94106
/// particular number of bytes but only a smaller number of bytes could be
95107
/// written.
108+
#[stable(feature = "rust1", since = "1.0.0")]
96109
WriteZero,
97-
/// This operation was interrupted
110+
/// This operation was interrupted.
111+
///
112+
/// Interrupted operations can typically be retried.
113+
#[stable(feature = "rust1", since = "1.0.0")]
98114
Interrupted,
99115
/// Any I/O error not part of this list.
116+
#[stable(feature = "rust1", since = "1.0.0")]
100117
Other,
118+
119+
/// Any I/O error not part of this list.
120+
#[unstable(feature = "std_misc",
121+
reason = "better expressed through extensible enums that this \
122+
enum cannot be exhaustively matched against")]
123+
#[doc(hidden)]
124+
__Nonexhaustive,
101125
}
102126

103127
impl Error {
@@ -134,6 +158,19 @@ impl Error {
134158
Error { repr: Repr::Os(code) }
135159
}
136160

161+
/// Returns the OS error that this error represents (if any).
162+
///
163+
/// If this `Error` was constructed via `last_os_error` then this function
164+
/// will return `Some`, otherwise it will return `None`.
165+
#[unstable(feature = "io", reason = "function was just added and the return \
166+
type may become an abstract OS error")]
167+
pub fn raw_os_error(&self) -> Option<i32> {
168+
match self.repr {
169+
Repr::Os(i) => Some(i),
170+
Repr::Custom(..) => None,
171+
}
172+
}
173+
137174
/// Return the corresponding `ErrorKind` for this error.
138175
#[stable(feature = "rust1", since = "1.0.0")]
139176
pub fn kind(&self) -> ErrorKind {

src/libstd/net/tcp.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -273,17 +273,19 @@ mod tests {
273273
match TcpListener::bind("1.1.1.1:9999") {
274274
Ok(..) => panic!(),
275275
Err(e) =>
276-
// EADDRNOTAVAIL is mapped to ConnectionRefused
277-
assert_eq!(e.kind(), ErrorKind::ConnectionRefused),
276+
assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
278277
}
279278
}
280279

281280
#[test]
282281
fn connect_error() {
283282
match TcpStream::connect("0.0.0.0:1") {
284283
Ok(..) => panic!(),
285-
Err(e) => assert!((e.kind() == ErrorKind::ConnectionRefused)
286-
|| (e.kind() == ErrorKind::InvalidInput)),
284+
Err(e) => assert!(e.kind() == ErrorKind::ConnectionRefused ||
285+
e.kind() == ErrorKind::InvalidInput ||
286+
e.kind() == ErrorKind::AddrInUse ||
287+
e.kind() == ErrorKind::AddrNotAvailable,
288+
"bad error: {} {:?}", e, e.kind()),
287289
}
288290
}
289291

@@ -535,7 +537,8 @@ mod tests {
535537
Ok(..) => panic!(),
536538
Err(e) => {
537539
assert!(e.kind() == ErrorKind::ConnectionRefused ||
538-
e.kind() == ErrorKind::Other,
540+
e.kind() == ErrorKind::Other ||
541+
e.kind() == ErrorKind::AddrInUse,
539542
"unknown error: {} {:?}", e, e.kind());
540543
}
541544
}

src/libstd/process.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ mod tests {
668668
#[test]
669669
fn test_process_output_fail_to_start() {
670670
match Command::new("/no-binary-by-this-name-should-exist").output() {
671-
Err(e) => assert_eq!(e.kind(), ErrorKind::FileNotFound),
671+
Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
672672
Ok(..) => panic!()
673673
}
674674
}

src/libstd/sys/unix/mod.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -139,22 +139,19 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
139139
libc::EPIPE => ErrorKind::BrokenPipe,
140140
libc::ENOTCONN => ErrorKind::NotConnected,
141141
libc::ECONNABORTED => ErrorKind::ConnectionAborted,
142-
libc::EADDRNOTAVAIL => ErrorKind::ConnectionRefused,
143-
libc::EADDRINUSE => ErrorKind::ConnectionRefused,
144-
libc::ENOENT => ErrorKind::FileNotFound,
145-
libc::EISDIR => ErrorKind::InvalidInput,
142+
libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
143+
libc::EADDRINUSE => ErrorKind::AddrInUse,
144+
libc::ENOENT => ErrorKind::NotFound,
146145
libc::EINTR => ErrorKind::Interrupted,
147146
libc::EINVAL => ErrorKind::InvalidInput,
148-
libc::ENOTTY => ErrorKind::MismatchedFileTypeForOperation,
149147
libc::ETIMEDOUT => ErrorKind::TimedOut,
150-
libc::ECANCELED => ErrorKind::TimedOut,
151-
libc::consts::os::posix88::EEXIST => ErrorKind::PathAlreadyExists,
148+
libc::consts::os::posix88::EEXIST => ErrorKind::AlreadyExists,
152149

153150
// These two constants can have the same value on some systems,
154151
// but different values on others, so we can't use a match
155152
// clause
156153
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
157-
ErrorKind::ResourceUnavailable,
154+
ErrorKind::WouldBlock,
158155

159156
_ => ErrorKind::Other,
160157
}

src/libstd/sys/windows/mod.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -149,25 +149,21 @@ pub fn decode_error_detailed(errno: i32) -> IoError {
149149
pub fn decode_error_kind(errno: i32) -> ErrorKind {
150150
match errno as libc::c_int {
151151
libc::ERROR_ACCESS_DENIED => ErrorKind::PermissionDenied,
152-
libc::ERROR_ALREADY_EXISTS => ErrorKind::PathAlreadyExists,
152+
libc::ERROR_ALREADY_EXISTS => ErrorKind::AlreadyExists,
153153
libc::ERROR_BROKEN_PIPE => ErrorKind::BrokenPipe,
154-
libc::ERROR_FILE_NOT_FOUND => ErrorKind::FileNotFound,
155-
libc::ERROR_INVALID_FUNCTION => ErrorKind::InvalidInput,
156-
libc::ERROR_INVALID_HANDLE => ErrorKind::MismatchedFileTypeForOperation,
157-
libc::ERROR_INVALID_NAME => ErrorKind::InvalidInput,
158-
libc::ERROR_NOTHING_TO_TERMINATE => ErrorKind::InvalidInput,
154+
libc::ERROR_FILE_NOT_FOUND => ErrorKind::NotFound,
159155
libc::ERROR_NO_DATA => ErrorKind::BrokenPipe,
160156
libc::ERROR_OPERATION_ABORTED => ErrorKind::TimedOut,
161157

162158
libc::WSAEACCES => ErrorKind::PermissionDenied,
163-
libc::WSAEADDRINUSE => ErrorKind::ConnectionRefused,
164-
libc::WSAEADDRNOTAVAIL => ErrorKind::ConnectionRefused,
159+
libc::WSAEADDRINUSE => ErrorKind::AddrInUse,
160+
libc::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
165161
libc::WSAECONNABORTED => ErrorKind::ConnectionAborted,
166162
libc::WSAECONNREFUSED => ErrorKind::ConnectionRefused,
167163
libc::WSAECONNRESET => ErrorKind::ConnectionReset,
168164
libc::WSAEINVAL => ErrorKind::InvalidInput,
169165
libc::WSAENOTCONN => ErrorKind::NotConnected,
170-
libc::WSAEWOULDBLOCK => ErrorKind::ResourceUnavailable,
166+
libc::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
171167

172168
_ => ErrorKind::Other,
173169
}

0 commit comments

Comments
 (0)