Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redefine ErrorKind::Other and stop using it in std. #85746

Merged
merged 4 commits into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,8 +880,7 @@ impl OpenOptions {
/// This function will return an error under a number of different
/// circumstances. Some of these error conditions are listed here, together
/// with their [`io::ErrorKind`]. The mapping to [`io::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.
/// part of the compatibility contract of the function.
///
/// * [`NotFound`]: The specified file does not exist and neither `create`
/// or `create_new` is set.
Expand All @@ -895,9 +894,11 @@ impl OpenOptions {
/// exists.
/// * [`InvalidInput`]: Invalid combinations of open options (truncate
/// 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.
/// * [`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
/// open files, too long filename, too many symbolic links in the
/// specified path (Unix-like systems only), etc.
Expand All @@ -913,7 +914,6 @@ impl OpenOptions {
/// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
/// [`InvalidInput`]: io::ErrorKind::InvalidInput
/// [`NotFound`]: io::ErrorKind::NotFound
/// [`Other`]: io::ErrorKind::Other
/// [`PermissionDenied`]: io::ErrorKind::PermissionDenied
#[stable(feature = "rust1", since = "1.0.0")]
pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
Expand Down Expand Up @@ -2190,7 +2190,7 @@ impl DirBuilder {
Some(p) => self.create_dir_all(p)?,
None => {
return Err(io::Error::new_const(
io::ErrorKind::Other,
io::ErrorKind::Uncategorized,
&"failed to create whole tree",
));
}
Expand Down
3 changes: 2 additions & 1 deletion library/std/src/fs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1329,7 +1329,8 @@ fn metadata_access_times() {
match (a.created(), b.created()) {
(Ok(t1), Ok(t2)) => assert!(t1 <= t2),
(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
&& e2.kind() == ErrorKind::Unsupported => {}
(a, b) => {
Expand Down
29 changes: 22 additions & 7 deletions library/std/src/io/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,17 @@ pub enum ErrorKind {
/// Interrupted operations can typically be retried.
#[stable(feature = "rust1", since = "1.0.0")]
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
/// [`ErrorKind`] variant in the future. It is not recommended to match
/// an error against `Other` and to expect any additional characteristics,
/// e.g., a specific [`Error::raw_os_error`] return value.
/// This can be used to construct your own [`Error`]s that do not match any
/// [`ErrorKind`].
///
/// 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")]
Other,
m-ou-se marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -191,6 +196,15 @@ pub enum ErrorKind {
/// to allocate enough memory.
#[stable(feature = "out_of_memory_error", since = "1.54.0")]
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 {
Expand All @@ -212,10 +226,11 @@ impl ErrorKind {
ErrorKind::TimedOut => "timed out",
ErrorKind::WriteZero => "write zero",
ErrorKind::Interrupted => "operation interrupted",
ErrorKind::Other => "other os error",
ErrorKind::UnexpectedEof => "unexpected end of file",
ErrorKind::Unsupported => "unsupported",
ErrorKind::OutOfMemory => "out of memory",
ErrorKind::Other => "other error",
ErrorKind::Uncategorized => "uncategorized error",
}
}
}
Expand Down Expand Up @@ -538,7 +553,7 @@ impl Error {
/// }
///
/// fn main() {
/// // Will print "Other".
/// // Will print "Uncategorized".
/// print_error(Error::last_os_error());
/// // Will print "AddrInUse".
/// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1592,7 +1592,7 @@ pub trait Write {
if output.error.is_err() {
output.error
} else {
Err(Error::new_const(ErrorKind::Other, &"formatter error"))
Err(Error::new_const(ErrorKind::Uncategorized, &"formatter error"))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/net/tcp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ fn double_bind() {
Err(e) => {
assert!(
e.kind() == ErrorKind::ConnectionRefused
|| e.kind() == ErrorKind::Other
|| e.kind() == ErrorKind::Uncategorized
|| e.kind() == ErrorKind::AddrInUse,
"unknown error: {} {:?}",
e,
Expand Down
3 changes: 2 additions & 1 deletion library/std/src/os/wasi/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
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"))
}
4 changes: 1 addition & 3 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1658,8 +1658,7 @@ impl Child {
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
/// error is returned.
///
/// 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.
/// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function.
///
/// This is equivalent to sending a SIGKILL on Unix platforms.
///
Expand All @@ -1680,7 +1679,6 @@ impl Child {
///
/// [`ErrorKind`]: io::ErrorKind
/// [`InvalidInput`]: io::ErrorKind::InvalidInput
/// [`Other`]: io::ErrorKind::Other
#[stable(feature = "process", since = "1.0.0")]
pub fn kill(&mut self) -> io::Result<()> {
self.handle.kill()
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/hermit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
x if x == 1 as i32 => ErrorKind::PermissionDenied,
x if x == 32 as i32 => ErrorKind::BrokenPipe,
x if x == 110 as i32 => ErrorKind::TimedOut,
_ => ErrorKind::Other,
_ => ErrorKind::Uncategorized,
}
}

Expand Down
51 changes: 28 additions & 23 deletions library/std/src/sys/hermit/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::time::Duration;
pub fn init() -> io::Result<()> {
if abi::network_init() < 0 {
return Err(io::Error::new_const(
ErrorKind::Other,
ErrorKind::Uncategorized,
&"Unable to initialize network interface",
));
}
Expand Down Expand Up @@ -51,7 +51,7 @@ impl TcpStream {
match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => Err(io::Error::new_const(
ErrorKind::Other,
ErrorKind::Uncategorized,
&"Unable to initiate a connection on a socket",
)),
}
Expand All @@ -65,44 +65,46 @@ impl TcpStream {
) {
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => Err(io::Error::new_const(
ErrorKind::Other,
ErrorKind::Uncategorized,
&"Unable to initiate a connection on a socket",
)),
}
}

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))
.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<()> {
abi::tcpstream::set_write_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 read_timeout(&self) -> io::Result<Option<Duration>> {
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)))
}

pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
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)))
}

pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
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> {
Expand All @@ -113,8 +115,9 @@ impl TcpStream {
let mut size: usize = 0;

for i in ioslice.iter_mut() {
let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..])
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?;
let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| {
io::Error::new_const(ErrorKind::Uncategorized, &"Unable to read on socket")
})?;

if ret != 0 {
size += ret;
Expand All @@ -138,7 +141,7 @@ impl TcpStream {

for i in ioslice.iter() {
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")
})?;
}

Expand All @@ -152,13 +155,13 @@ impl TcpStream {

pub fn peer_addr(&self) -> io::Result<SocketAddr> {
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 {
Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::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"));
}
};

Expand All @@ -170,8 +173,9 @@ impl TcpStream {
}

pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket"))
abi::tcpstream::shutdown(*self.0.as_inner(), how as i32).map_err(|_| {
io::Error::new_const(ErrorKind::Uncategorized, &"unable to shutdown socket")
})
}

pub fn duplicate(&self) -> io::Result<TcpStream> {
Expand All @@ -180,31 +184,32 @@ impl TcpStream {

pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
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> {
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<()> {
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> {
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>> {
unsupported()
}

pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode)
.map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode"))
abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| {
io::Error::new_const(ErrorKind::Uncategorized, &"unable to set blocking mode")
})
}
}

Expand All @@ -230,12 +235,12 @@ impl TcpListener {

pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
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 {
Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::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"));
}
};

Expand Down
8 changes: 4 additions & 4 deletions library/std/src/sys/hermit/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl io::Write for Stdout {
unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }

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 {
Ok(len as usize)
}
Expand All @@ -52,7 +52,7 @@ impl io::Write for Stdout {
unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }

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 {
Ok(len as usize)
}
Expand Down Expand Up @@ -81,7 +81,7 @@ impl io::Write for Stderr {
unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }

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 {
Ok(len as usize)
}
Expand All @@ -93,7 +93,7 @@ impl io::Write for Stderr {
unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }

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 {
Ok(len as usize)
}
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/hermit/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Thread {
// 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.
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 {
Ok(Thread { tid: tid })
};
Expand Down
Loading