1
Fork 0

Auto merge of #85746 - m-ou-se:io-error-other, r=joshtriplett

Redefine `ErrorKind::Other` and stop using it in std.

This implements the idea I shared yesterday in the libs meeting when we were discussing how to handle adding new `ErrorKind`s to the standard library: This redefines `Other` to be for *user defined errors only*, and changes all uses of `Other` in the standard library to a `#[doc(hidden)]` and permanently `#[unstable]` `ErrorKind` that users can not match on. This ensures that adding `ErrorKind`s at a later point in time is not a breaking change, since the user couldn't match on these errors anyway. This way, we use the `#[non_exhaustive]` property of the enum in a more effective way.

Open questions:
- How do we check this change doesn't cause too much breakage? Will a crate run help and be enough?
- How do we ensure we don't accidentally start using `Other` again in the standard library? We don't have a `pub(not crate)` or `#[deprecated(in this crate only)]`.

cc https://github.com/rust-lang/rust/pull/79965

cc `@rust-lang/libs` `@ijackson`

r? `@dtolnay`
This commit is contained in:
bors 2021-07-02 09:01:42 +00:00
commit f9fa13f705
24 changed files with 99 additions and 74 deletions

View file

@ -880,8 +880,7 @@ impl OpenOptions {
/// This function will return an error under a number of different /// This function will return an error under a number of different
/// circumstances. Some of these error conditions are listed here, together /// circumstances. Some of these error conditions are listed here, together
/// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not
/// part of the compatibility contract of the function, especially the /// part of the compatibility contract of the function.
/// [`Other`] kind might change to more specific kinds in the future.
/// ///
/// * [`NotFound`]: The specified file does not exist and neither `create` /// * [`NotFound`]: The specified file does not exist and neither `create`
/// or `create_new` is set. /// or `create_new` is set.
@ -895,9 +894,11 @@ impl OpenOptions {
/// exists. /// exists.
/// * [`InvalidInput`]: Invalid combinations of open options (truncate /// * [`InvalidInput`]: Invalid combinations of open options (truncate
/// without write access, no access mode set, etc.). /// without write access, no access mode set, etc.).
/// * [`Other`]: One of the directory components of the specified file path ///
/// The following errors don't match any existing [`io::ErrorKind`] at the moment:
/// * One of the directory components of the specified file path
/// was not, in fact, a directory. /// was not, in fact, a directory.
/// * [`Other`]: Filesystem-level errors: full disk, write permission /// * Filesystem-level errors: full disk, write permission
/// requested on a read-only file system, exceeded disk quota, too many /// requested on a read-only file system, exceeded disk quota, too many
/// open files, too long filename, too many symbolic links in the /// open files, too long filename, too many symbolic links in the
/// specified path (Unix-like systems only), etc. /// specified path (Unix-like systems only), etc.
@ -913,7 +914,6 @@ impl OpenOptions {
/// [`AlreadyExists`]: io::ErrorKind::AlreadyExists /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
/// [`InvalidInput`]: io::ErrorKind::InvalidInput /// [`InvalidInput`]: io::ErrorKind::InvalidInput
/// [`NotFound`]: io::ErrorKind::NotFound /// [`NotFound`]: io::ErrorKind::NotFound
/// [`Other`]: io::ErrorKind::Other
/// [`PermissionDenied`]: io::ErrorKind::PermissionDenied /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> { pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
@ -2216,7 +2216,7 @@ impl DirBuilder {
Some(p) => self.create_dir_all(p)?, Some(p) => self.create_dir_all(p)?,
None => { None => {
return Err(io::Error::new_const( return Err(io::Error::new_const(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&"failed to create whole tree", &"failed to create whole tree",
)); ));
} }

View file

@ -1329,7 +1329,8 @@ fn metadata_access_times() {
match (a.created(), b.created()) { match (a.created(), b.created()) {
(Ok(t1), Ok(t2)) => assert!(t1 <= t2), (Ok(t1), Ok(t2)) => assert!(t1 <= t2),
(Err(e1), Err(e2)) (Err(e1), Err(e2))
if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other if e1.kind() == ErrorKind::Uncategorized
&& e2.kind() == ErrorKind::Uncategorized
|| e1.kind() == ErrorKind::Unsupported || e1.kind() == ErrorKind::Unsupported
&& e2.kind() == ErrorKind::Unsupported => {} && e2.kind() == ErrorKind::Unsupported => {}
(a, b) => { (a, b) => {

View file

@ -163,12 +163,17 @@ pub enum ErrorKind {
/// Interrupted operations can typically be retried. /// Interrupted operations can typically be retried.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
Interrupted, Interrupted,
/// Any I/O error not part of this list.
/// A custom error that does not fall under any other I/O error kind.
/// ///
/// Errors that are `Other` now may move to a different or a new /// This can be used to construct your own [`Error`]s that do not match any
/// [`ErrorKind`] variant in the future. It is not recommended to match /// [`ErrorKind`].
/// an error against `Other` and to expect any additional characteristics, ///
/// e.g., a specific [`Error::raw_os_error`] return value. /// This [`ErrorKind`] is not used by the standard library.
///
/// Errors from the standard library that do not fall under any of the I/O
/// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
/// New [`ErrorKind`]s might be added in the future for some of those.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
Other, Other,
@ -191,6 +196,15 @@ pub enum ErrorKind {
/// to allocate enough memory. /// to allocate enough memory.
#[stable(feature = "out_of_memory_error", since = "1.54.0")] #[stable(feature = "out_of_memory_error", since = "1.54.0")]
OutOfMemory, OutOfMemory,
/// Any I/O error from the standard library that's not part of this list.
///
/// Errors that are `Uncategorized` now may move to a different or a new
/// [`ErrorKind`] variant in the future. It is not recommended to match
/// an error against `Uncategorized`; use a wildcard match (`_`) instead.
#[unstable(feature = "io_error_uncategorized", issue = "none")]
#[doc(hidden)]
Uncategorized,
} }
impl ErrorKind { impl ErrorKind {
@ -212,10 +226,11 @@ impl ErrorKind {
ErrorKind::TimedOut => "timed out", ErrorKind::TimedOut => "timed out",
ErrorKind::WriteZero => "write zero", ErrorKind::WriteZero => "write zero",
ErrorKind::Interrupted => "operation interrupted", ErrorKind::Interrupted => "operation interrupted",
ErrorKind::Other => "other os error",
ErrorKind::UnexpectedEof => "unexpected end of file", ErrorKind::UnexpectedEof => "unexpected end of file",
ErrorKind::Unsupported => "unsupported", ErrorKind::Unsupported => "unsupported",
ErrorKind::OutOfMemory => "out of memory", ErrorKind::OutOfMemory => "out of memory",
ErrorKind::Other => "other error",
ErrorKind::Uncategorized => "uncategorized error",
} }
} }
} }
@ -538,7 +553,7 @@ impl Error {
/// } /// }
/// ///
/// fn main() { /// fn main() {
/// // Will print "Other". /// // Will print "Uncategorized".
/// print_error(Error::last_os_error()); /// print_error(Error::last_os_error());
/// // Will print "AddrInUse". /// // Will print "AddrInUse".
/// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));

View file

@ -1644,7 +1644,7 @@ pub trait Write {
if output.error.is_err() { if output.error.is_err() {
output.error output.error
} else { } else {
Err(Error::new_const(ErrorKind::Other, &"formatter error")) Err(Error::new_const(ErrorKind::Uncategorized, &"formatter error"))
} }
} }
} }

View file

@ -342,7 +342,7 @@ fn double_bind() {
Err(e) => { Err(e) => {
assert!( assert!(
e.kind() == ErrorKind::ConnectionRefused e.kind() == ErrorKind::ConnectionRefused
|| e.kind() == ErrorKind::Other || e.kind() == ErrorKind::Uncategorized
|| e.kind() == ErrorKind::AddrInUse, || e.kind() == ErrorKind::AddrInUse,
"unknown error: {} {:?}", "unknown error: {} {:?}",
e, e,

View file

@ -532,5 +532,6 @@ pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) ->
} }
fn osstr2str(f: &OsStr) -> io::Result<&str> { fn osstr2str(f: &OsStr) -> io::Result<&str> {
f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) f.to_str()
.ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8"))
} }

View file

@ -1658,8 +1658,7 @@ impl Child {
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
/// error is returned. /// error is returned.
/// ///
/// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function, /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function.
/// especially the [`Other`] kind might change to more specific kinds in the future.
/// ///
/// This is equivalent to sending a SIGKILL on Unix platforms. /// This is equivalent to sending a SIGKILL on Unix platforms.
/// ///
@ -1680,7 +1679,6 @@ impl Child {
/// ///
/// [`ErrorKind`]: io::ErrorKind /// [`ErrorKind`]: io::ErrorKind
/// [`InvalidInput`]: io::ErrorKind::InvalidInput /// [`InvalidInput`]: io::ErrorKind::InvalidInput
/// [`Other`]: io::ErrorKind::Other
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn kill(&mut self) -> io::Result<()> { pub fn kill(&mut self) -> io::Result<()> {
self.handle.kill() self.handle.kill()

View file

@ -149,7 +149,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
x if x == 1 as i32 => ErrorKind::PermissionDenied, x if x == 1 as i32 => ErrorKind::PermissionDenied,
x if x == 32 as i32 => ErrorKind::BrokenPipe, x if x == 32 as i32 => ErrorKind::BrokenPipe,
x if x == 110 as i32 => ErrorKind::TimedOut, x if x == 110 as i32 => ErrorKind::TimedOut,
_ => ErrorKind::Other, _ => ErrorKind::Uncategorized,
} }
} }

View file

@ -15,7 +15,7 @@ use crate::time::Duration;
pub fn init() -> io::Result<()> { pub fn init() -> io::Result<()> {
if abi::network_init() < 0 { if abi::network_init() < 0 {
return Err(io::Error::new_const( return Err(io::Error::new_const(
ErrorKind::Other, ErrorKind::Uncategorized,
&"Unable to initialize network interface", &"Unable to initialize network interface",
)); ));
} }
@ -51,7 +51,7 @@ impl TcpStream {
match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => Err(io::Error::new_const( _ => Err(io::Error::new_const(
ErrorKind::Other, ErrorKind::Uncategorized,
&"Unable to initiate a connection on a socket", &"Unable to initiate a connection on a socket",
)), )),
} }
@ -65,7 +65,7 @@ impl TcpStream {
) { ) {
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => Err(io::Error::new_const( _ => Err(io::Error::new_const(
ErrorKind::Other, ErrorKind::Uncategorized,
&"Unable to initiate a connection on a socket", &"Unable to initiate a connection on a socket",
)), )),
} }
@ -73,7 +73,9 @@ impl TcpStream {
pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> { pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64)) abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) .map_err(|_| {
io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value")
})
} }
pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> { pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
@ -81,12 +83,12 @@ impl TcpStream {
*self.0.as_inner(), *self.0.as_inner(),
duration.map(|d| d.as_millis() as u64), duration.map(|d| d.as_millis() as u64),
) )
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value"))
} }
pub fn read_timeout(&self) -> io::Result<Option<Duration>> { pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| { let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| {
io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value")
})?; })?;
Ok(duration.map(|d| Duration::from_millis(d))) Ok(duration.map(|d| Duration::from_millis(d)))
@ -94,7 +96,7 @@ impl TcpStream {
pub fn write_timeout(&self) -> io::Result<Option<Duration>> { pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| { let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| {
io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value")
})?; })?;
Ok(duration.map(|d| Duration::from_millis(d))) Ok(duration.map(|d| Duration::from_millis(d)))
@ -102,7 +104,7 @@ impl TcpStream {
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
abi::tcpstream::peek(*self.0.as_inner(), buf) abi::tcpstream::peek(*self.0.as_inner(), buf)
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peek failed"))
} }
pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> { pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> {
@ -113,8 +115,9 @@ impl TcpStream {
let mut size: usize = 0; let mut size: usize = 0;
for i in ioslice.iter_mut() { for i in ioslice.iter_mut() {
let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]) let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| {
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?; io::Error::new_const(ErrorKind::Uncategorized, &"Unable to read on socket")
})?;
if ret != 0 { if ret != 0 {
size += ret; size += ret;
@ -138,7 +141,7 @@ impl TcpStream {
for i in ioslice.iter() { for i in ioslice.iter() {
size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| { size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| {
io::Error::new_const(ErrorKind::Other, &"Unable to write on socket") io::Error::new_const(ErrorKind::Uncategorized, &"Unable to write on socket")
})?; })?;
} }
@ -152,13 +155,13 @@ impl TcpStream {
pub fn peer_addr(&self) -> io::Result<SocketAddr> { pub fn peer_addr(&self) -> io::Result<SocketAddr> {
let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner()) let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"peer_addr failed"))?; .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"))?;
let saddr = match ipaddr { let saddr = match ipaddr {
Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
_ => { _ => {
return Err(io::Error::new_const(ErrorKind::Other, &"peer_addr failed")); return Err(io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"));
} }
}; };
@ -170,8 +173,9 @@ impl TcpStream {
} }
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
abi::tcpstream::shutdown(*self.0.as_inner(), how as i32) abi::tcpstream::shutdown(*self.0.as_inner(), how as i32).map_err(|_| {
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket")) io::Error::new_const(ErrorKind::Uncategorized, &"unable to shutdown socket")
})
} }
pub fn duplicate(&self) -> io::Result<TcpStream> { pub fn duplicate(&self) -> io::Result<TcpStream> {
@ -180,22 +184,22 @@ impl TcpStream {
pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nodelay(*self.0.as_inner(), mode) abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed"))
} }
pub fn nodelay(&self) -> io::Result<bool> { pub fn nodelay(&self) -> io::Result<bool> {
abi::tcpstream::nodelay(*self.0.as_inner()) abi::tcpstream::nodelay(*self.0.as_inner())
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"nodelay failed")) .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"nodelay failed"))
} }
pub fn set_ttl(&self, tll: u32) -> io::Result<()> { pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
abi::tcpstream::set_tll(*self.0.as_inner(), tll) abi::tcpstream::set_tll(*self.0.as_inner(), tll)
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set TTL")) .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to set TTL"))
} }
pub fn ttl(&self) -> io::Result<u32> { pub fn ttl(&self) -> io::Result<u32> {
abi::tcpstream::get_tll(*self.0.as_inner()) abi::tcpstream::get_tll(*self.0.as_inner())
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to get TTL")) .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to get TTL"))
} }
pub fn take_error(&self) -> io::Result<Option<io::Error>> { pub fn take_error(&self) -> io::Result<Option<io::Error>> {
@ -203,8 +207,9 @@ impl TcpStream {
} }
pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode) abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| {
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode")) io::Error::new_const(ErrorKind::Uncategorized, &"unable to set blocking mode")
})
} }
} }
@ -230,12 +235,12 @@ impl TcpListener {
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port()) let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"accept failed"))?; .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"))?;
let saddr = match ipaddr { let saddr = match ipaddr {
Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
_ => { _ => {
return Err(io::Error::new_const(ErrorKind::Other, &"accept failed")); return Err(io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"));
} }
}; };

View file

@ -40,7 +40,7 @@ impl io::Write for Stdout {
unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
if len < 0 { if len < 0 {
Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print"))
} else { } else {
Ok(len as usize) Ok(len as usize)
} }
@ -52,7 +52,7 @@ impl io::Write for Stdout {
unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
if len < 0 { if len < 0 {
Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print"))
} else { } else {
Ok(len as usize) Ok(len as usize)
} }
@ -81,7 +81,7 @@ impl io::Write for Stderr {
unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
if len < 0 { if len < 0 {
Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print"))
} else { } else {
Ok(len as usize) Ok(len as usize)
} }
@ -93,7 +93,7 @@ impl io::Write for Stderr {
unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
if len < 0 { if len < 0 {
Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print"))
} else { } else {
Ok(len as usize) Ok(len as usize)
} }

View file

@ -39,7 +39,7 @@ impl Thread {
// The thread failed to start and as a result p was not consumed. Therefore, it is // The thread failed to start and as a result p was not consumed. Therefore, it is
// safe to reconstruct the box so that it gets deallocated. // safe to reconstruct the box so that it gets deallocated.
drop(Box::from_raw(p)); drop(Box::from_raw(p));
Err(io::Error::new_const(io::ErrorKind::Other, &"Unable to create thread!")) Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Unable to create thread!"))
} else { } else {
Ok(Thread { tid: tid }) Ok(Thread { tid: tid })
}; };

View file

@ -70,7 +70,7 @@ pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false); static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) { if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
Err(crate::io::Error::new_const( Err(crate::io::Error::new_const(
ErrorKind::Other, ErrorKind::Uncategorized,
&"operation can't be trusted to have any effect on SGX", &"operation can't be trusted to have any effect on SGX",
)) ))
} else { } else {
@ -115,11 +115,11 @@ pub fn decode_error_kind(code: i32) -> ErrorKind {
} else if code == Error::Interrupted as _ { } else if code == Error::Interrupted as _ {
ErrorKind::Interrupted ErrorKind::Interrupted
} else if code == Error::Other as _ { } else if code == Error::Other as _ {
ErrorKind::Other ErrorKind::Uncategorized
} else if code == Error::UnexpectedEof as _ { } else if code == Error::UnexpectedEof as _ {
ErrorKind::UnexpectedEof ErrorKind::UnexpectedEof
} else { } else {
ErrorKind::Other ErrorKind::Uncategorized
} }
} }

View file

@ -466,7 +466,7 @@ pub struct LookupHost(!);
impl LookupHost { impl LookupHost {
fn new(host: String) -> io::Result<LookupHost> { fn new(host: String) -> io::Result<LookupHost> {
Err(io::Error::new(io::ErrorKind::Other, NonIpSockAddr { host })) Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host }))
} }
pub fn port(&self) -> u16 { pub fn port(&self) -> u16 {

View file

@ -65,7 +65,7 @@ impl io::Write for Stderr {
pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
pub fn is_ebadf(err: &io::Error) -> bool { pub fn is_ebadf(err: &io::Error) -> bool {
// FIXME: Rust normally maps Unix EBADF to `Other` // FIXME: Rust normally maps Unix EBADF to `Uncategorized`
err.raw_os_error() == Some(abi::Error::BrokenPipe as _) err.raw_os_error() == Some(abi::Error::BrokenPipe as _)
} }

View file

@ -358,7 +358,7 @@ impl FileAttr {
})) }))
} else { } else {
Err(io::Error::new_const( Err(io::Error::new_const(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&"creation time is not available for the filesystem", &"creation time is not available for the filesystem",
)) ))
}; };

View file

@ -155,7 +155,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
// clause // clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock, x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,
_ => ErrorKind::Other, _ => ErrorKind::Uncategorized,
} }
} }

View file

@ -38,7 +38,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned() str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned()
}; };
Err(io::Error::new( Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&format!("failed to lookup address information: {}", detail)[..], &format!("failed to lookup address information: {}", detail)[..],
)) ))
} }
@ -178,7 +178,7 @@ impl Socket {
if pollfd.revents & libc::POLLHUP != 0 { if pollfd.revents & libc::POLLHUP != 0 {
let e = self.take_error()?.unwrap_or_else(|| { let e = self.take_error()?.unwrap_or_else(|| {
io::Error::new_const( io::Error::new_const(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&"no error set after POLLHUP", &"no error set after POLLHUP",
) )
}); });

View file

@ -279,7 +279,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
))?; ))?;
if path_len <= 1 { if path_len <= 1 {
return Err(io::Error::new_const( return Err(io::Error::new_const(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&"KERN_PROC_PATHNAME sysctl returned zero-length string", &"KERN_PROC_PATHNAME sysctl returned zero-length string",
)); ));
} }
@ -302,7 +302,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
return crate::fs::read_link(curproc_exe); return crate::fs::read_link(curproc_exe);
} }
Err(io::Error::new_const( Err(io::Error::new_const(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&"/proc/curproc/exe doesn't point to regular file.", &"/proc/curproc/exe doesn't point to regular file.",
)) ))
} }
@ -320,7 +320,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?; cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?;
argv.set_len(argv_len as usize); argv.set_len(argv_len as usize);
if argv[0].is_null() { if argv[0].is_null() {
return Err(io::Error::new_const(io::ErrorKind::Other, &"no current exe available")); return Err(io::Error::new_const(
io::ErrorKind::Uncategorized,
&"no current exe available",
));
} }
let argv0 = CStr::from_ptr(argv[0]).to_bytes(); let argv0 = CStr::from_ptr(argv[0]).to_bytes();
if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') { if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
@ -335,7 +338,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
pub fn current_exe() -> io::Result<PathBuf> { pub fn current_exe() -> io::Result<PathBuf> {
match crate::fs::read_link("/proc/self/exe") { match crate::fs::read_link("/proc/self/exe") {
Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const( Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&"no /proc/self/exe available. Is /proc mounted?", &"no /proc/self/exe available. Is /proc mounted?",
)), )),
other => other, other => other,
@ -422,7 +425,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
_get_next_image_info(0, &mut cookie, &mut info, mem::size_of::<image_info>() as i32); _get_next_image_info(0, &mut cookie, &mut info, mem::size_of::<image_info>() as i32);
if result != 0 { if result != 0 {
use crate::io::ErrorKind; use crate::io::ErrorKind;
Err(io::Error::new_const(ErrorKind::Other, &"Error getting executable path")) Err(io::Error::new_const(ErrorKind::Uncategorized, &"Error getting executable path"))
} else { } else {
let name = CStr::from_ptr(info.name.as_ptr()).to_bytes(); let name = CStr::from_ptr(info.name.as_ptr()).to_bytes();
Ok(PathBuf::from(OsStr::from_bytes(name))) Ok(PathBuf::from(OsStr::from_bytes(name)))

View file

@ -30,7 +30,7 @@ pub fn unsupported_err() -> std_io::Error {
} }
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Other crate::io::ErrorKind::Uncategorized
} }
pub fn abort_internal() -> ! { pub fn abort_internal() -> ! {

View file

@ -648,7 +648,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
through which {:?} could be opened", through which {:?} could be opened",
p p
); );
return Err(io::Error::new(io::ErrorKind::Other, msg)); return Err(io::Error::new(io::ErrorKind::Uncategorized, msg));
} }
let relative = CStr::from_ptr(relative_path).to_bytes().to_vec(); let relative = CStr::from_ptr(relative_path).to_bytes().to_vec();
@ -670,7 +670,8 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
} }
pub fn osstr2str(f: &OsStr) -> io::Result<&str> { pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) f.to_str()
.ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8"))
} }
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {

View file

@ -58,7 +58,7 @@ pub use common::*;
pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
use std_io::ErrorKind::*; use std_io::ErrorKind::*;
if errno > u16::MAX as i32 || errno < 0 { if errno > u16::MAX as i32 || errno < 0 {
return Other; return Uncategorized;
} }
match errno as u16 { match errno as u16 {
wasi::ERRNO_CONNREFUSED => ConnectionRefused, wasi::ERRNO_CONNREFUSED => ConnectionRefused,
@ -77,7 +77,7 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
wasi::ERRNO_AGAIN => WouldBlock, wasi::ERRNO_AGAIN => WouldBlock,
wasi::ERRNO_NOSYS => Unsupported, wasi::ERRNO_NOSYS => Unsupported,
wasi::ERRNO_NOMEM => OutOfMemory, wasi::ERRNO_NOMEM => OutOfMemory,
_ => Other, _ => Uncategorized,
} }
} }

View file

@ -514,7 +514,7 @@ impl File {
} }
_ => { _ => {
return Err(io::Error::new_const( return Err(io::Error::new_const(
io::ErrorKind::Other, io::ErrorKind::Uncategorized,
&"Unsupported reparse point type", &"Unsupported reparse point type",
)); ));
} }
@ -961,9 +961,8 @@ pub fn try_exists(path: &Path) -> io::Result<bool> {
// `ERROR_SHARING_VIOLATION` means that the file has been locked by // `ERROR_SHARING_VIOLATION` means that the file has been locked by
// another process. This is often temporary so we simply report it // another process. This is often temporary so we simply report it
// as the file existing. // as the file existing.
io::ErrorKind::Other if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => { _ if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => Ok(true),
Ok(true)
}
// Other errors such as `ERROR_ACCESS_DENIED` may indicate that the // Other errors such as `ERROR_ACCESS_DENIED` may indicate that the
// file exists. However, these types of errors are usually more // file exists. However, these types of errors are usually more
// permanent so we report them here. // permanent so we report them here.

View file

@ -103,7 +103,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
c::WSAEWOULDBLOCK => ErrorKind::WouldBlock, c::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
c::WSAETIMEDOUT => ErrorKind::TimedOut, c::WSAETIMEDOUT => ErrorKind::TimedOut,
_ => ErrorKind::Other, _ => ErrorKind::Uncategorized,
} }
} }

View file

@ -1,5 +1,7 @@
// run-pass // run-pass
#![feature(io_error_uncategorized)]
use std::fmt; use std::fmt;
use std::io::{self, Error, Write, sink}; use std::io::{self, Error, Write, sink};
@ -13,7 +15,7 @@ impl fmt::Display for ErrorDisplay {
struct ErrorWriter; struct ErrorWriter;
const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Other; const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Uncategorized;
const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected; const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected;
impl Write for ErrorWriter { impl Write for ErrorWriter {