mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #154654 - bushrat011899:core_io_error_kind, r=Mark-Simulacrum
Move `std::io::ErrorKind` to `core::io` ACP: https://github.com/rust-lang/libs-team/issues/755 Tracking issue: https://github.com/rust-lang/rust/issues/154046 Related: https://github.com/rust-lang/rust/pull/152918 ## Description I consider rust-lang/rust#154046 to be really important for `no_std`, but I'm concerned rust-lang/rust#152918 might be too controversial. As an alternative, I'd like to propose starting small with `ErrorKind`, since it can be moved somewhat trivially. It has no dependencies on functionality in `std`, no platform specific behaviour, and could provide an excellent bridging point for `no_std` IO libraries. Since `std::io::Error` implements `From<ErrorKind>`, libraries could write functions which return `Result<T, core::io::ErrorKind>`, and therefore be usable in `std`-using libraries with the `?` operator. For that reason, I'd consider this to be a worthwhile change even if the rest of `std::io` couldn't be moved to `core`/`alloc`, and entirely compatible with any efforts to make such a change in the future. ## Notes * This is my first PR against Rust, please let me know if there's anything I should be doing that I have not done. I tried reading through the library contributors guide but I'm sure I've missed _something_. * No AI tooling of any kind was used in the creation of this PR. * I believe it's appropriate that this be a part of the linked tracking issue, but please let me know if that's not the case!
This commit is contained in:
@@ -0,0 +1,372 @@
|
||||
#![unstable(feature = "core_io", issue = "154046")]
|
||||
|
||||
use crate::fmt;
|
||||
|
||||
/// A list specifying general categories of I/O error.
|
||||
///
|
||||
/// This list is intended to grow over time and it is not recommended to
|
||||
/// exhaustively match against it.
|
||||
///
|
||||
/// # Handling errors and matching on `ErrorKind`
|
||||
///
|
||||
/// In application code, use `match` for the `ErrorKind` values you are
|
||||
/// expecting; use `_` to match "all other errors".
|
||||
///
|
||||
/// In comprehensive and thorough tests that want to verify that a test doesn't
|
||||
/// return any known incorrect error kind, you may want to cut-and-paste the
|
||||
/// current full list of errors from here into your test code, and then match
|
||||
/// `_` as the correct case. This seems counterintuitive, but it will make your
|
||||
/// tests more robust. In particular, if you want to verify that your code does
|
||||
/// produce an unrecognized error kind, the robust solution is to check for all
|
||||
/// the recognized error kinds and fail in those cases.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "io_errorkind")]
|
||||
#[allow(deprecated)]
|
||||
#[non_exhaustive]
|
||||
pub enum ErrorKind {
|
||||
/// An entity was not found, often a file.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
NotFound,
|
||||
/// The operation lacked the necessary privileges to complete.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
PermissionDenied,
|
||||
/// The connection was refused by the remote server.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
ConnectionRefused,
|
||||
/// The connection was reset by the remote server.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
ConnectionReset,
|
||||
/// The remote host is not reachable.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
HostUnreachable,
|
||||
/// The network containing the remote host is not reachable.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NetworkUnreachable,
|
||||
/// The connection was aborted (terminated) by the remote server.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
ConnectionAborted,
|
||||
/// The network operation failed because it was not connected yet.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
NotConnected,
|
||||
/// A socket address could not be bound because the address is already in
|
||||
/// use elsewhere.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
AddrInUse,
|
||||
/// A nonexistent interface was requested or the requested address was not
|
||||
/// local.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
AddrNotAvailable,
|
||||
/// The system's networking is down.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NetworkDown,
|
||||
/// The operation failed because a pipe was closed.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
BrokenPipe,
|
||||
/// An entity already exists, often a file.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
AlreadyExists,
|
||||
/// The operation needs to block to complete, but the blocking operation was
|
||||
/// requested to not occur.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
WouldBlock,
|
||||
/// A filesystem object is, unexpectedly, not a directory.
|
||||
///
|
||||
/// For example, a filesystem path was specified where one of the intermediate directory
|
||||
/// components was, in fact, a plain file.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NotADirectory,
|
||||
/// The filesystem object is, unexpectedly, a directory.
|
||||
///
|
||||
/// A directory was specified when a non-directory was expected.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
IsADirectory,
|
||||
/// A non-empty directory was specified where an empty directory was expected.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
DirectoryNotEmpty,
|
||||
/// The filesystem or storage medium is read-only, but a write operation was attempted.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ReadOnlyFilesystem,
|
||||
/// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
|
||||
///
|
||||
/// There was a loop (or excessively long chain) resolving a filesystem object
|
||||
/// or file IO object.
|
||||
///
|
||||
/// On Unix this is usually the result of a symbolic link loop; or, of exceeding the
|
||||
/// system-specific limit on the depth of symlink traversal.
|
||||
#[unstable(feature = "io_error_more", issue = "86442")]
|
||||
FilesystemLoop,
|
||||
/// Stale network file handle.
|
||||
///
|
||||
/// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
|
||||
/// by problems with the network or server.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
StaleNetworkFileHandle,
|
||||
/// A parameter was incorrect.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
InvalidInput,
|
||||
/// Data not valid for the operation were encountered.
|
||||
///
|
||||
/// Unlike [`InvalidInput`], this typically means that the operation
|
||||
/// parameters were valid, however the error was caused by malformed
|
||||
/// input data.
|
||||
///
|
||||
/// For example, a function that reads a file into a string will error with
|
||||
/// `InvalidData` if the file's contents are not valid UTF-8.
|
||||
///
|
||||
/// [`InvalidInput`]: ErrorKind::InvalidInput
|
||||
#[stable(feature = "io_invalid_data", since = "1.2.0")]
|
||||
InvalidData,
|
||||
/// The I/O operation's timeout expired, causing it to be canceled.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
TimedOut,
|
||||
/// An error returned when an operation could not be completed because a
|
||||
/// call to an underlying writer returned [`Ok(0)`].
|
||||
///
|
||||
/// This typically means that an operation could only succeed if it wrote a
|
||||
/// particular number of bytes but only a smaller number of bytes could be
|
||||
/// written.
|
||||
///
|
||||
/// [`Ok(0)`]: Ok
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
WriteZero,
|
||||
/// The underlying storage (typically, a filesystem) is full.
|
||||
///
|
||||
/// This does not include out of quota errors.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
StorageFull,
|
||||
/// Seek on unseekable file.
|
||||
///
|
||||
/// Seeking was attempted on an open file handle which is not suitable for seeking - for
|
||||
/// example, on Unix, a named pipe opened with `File::open`.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NotSeekable,
|
||||
/// Filesystem quota or some other kind of quota was exceeded.
|
||||
#[stable(feature = "io_error_quota_exceeded", since = "1.85.0")]
|
||||
QuotaExceeded,
|
||||
/// File larger than allowed or supported.
|
||||
///
|
||||
/// This might arise from a hard limit of the underlying filesystem or file access API, or from
|
||||
/// an administratively imposed resource limitation. Simple disk full, and out of quota, have
|
||||
/// their own errors.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
FileTooLarge,
|
||||
/// Resource is busy.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ResourceBusy,
|
||||
/// Executable file is busy.
|
||||
///
|
||||
/// An attempt was made to write to a file which is also in use as a running program. (Not all
|
||||
/// operating systems detect this situation.)
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ExecutableFileBusy,
|
||||
/// Deadlock (avoided).
|
||||
///
|
||||
/// A file locking operation would result in deadlock. This situation is typically detected, if
|
||||
/// at all, on a best-effort basis.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
Deadlock,
|
||||
/// Cross-device or cross-filesystem (hard) link or rename.
|
||||
#[stable(feature = "io_error_crosses_devices", since = "1.85.0")]
|
||||
CrossesDevices,
|
||||
/// Too many (hard) links to the same filesystem object.
|
||||
///
|
||||
/// The filesystem does not support making so many hardlinks to the same file.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
TooManyLinks,
|
||||
/// A filename was invalid.
|
||||
///
|
||||
/// This error can also occur if a length limit for a name was exceeded.
|
||||
#[stable(feature = "io_error_invalid_filename", since = "1.87.0")]
|
||||
InvalidFilename,
|
||||
/// Program argument list too long.
|
||||
///
|
||||
/// When trying to run an external program, a system or process limit on the size of the
|
||||
/// arguments would have been exceeded.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ArgumentListTooLong,
|
||||
/// This operation was interrupted.
|
||||
///
|
||||
/// Interrupted operations can typically be retried.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Interrupted,
|
||||
|
||||
/// This operation is unsupported on this platform.
|
||||
///
|
||||
/// This means that the operation can never succeed.
|
||||
#[stable(feature = "unsupported_error", since = "1.53.0")]
|
||||
Unsupported,
|
||||
|
||||
// ErrorKinds which are primarily categorisations for OS error
|
||||
// codes should be added above.
|
||||
//
|
||||
/// An error returned when an operation could not be completed because an
|
||||
/// "end of file" was reached prematurely.
|
||||
///
|
||||
/// This typically means that an operation could only succeed if it read a
|
||||
/// particular number of bytes but only a smaller number of bytes could be
|
||||
/// read.
|
||||
#[stable(feature = "read_exact", since = "1.6.0")]
|
||||
UnexpectedEof,
|
||||
|
||||
/// An operation could not be completed, because it failed
|
||||
/// to allocate enough memory.
|
||||
#[stable(feature = "out_of_memory_error", since = "1.54.0")]
|
||||
OutOfMemory,
|
||||
|
||||
/// The operation was partially successful and needs to be checked
|
||||
/// later on due to not blocking.
|
||||
#[unstable(feature = "io_error_inprogress", issue = "130840")]
|
||||
InProgress,
|
||||
|
||||
// "Unusual" error kinds which do not correspond simply to (sets
|
||||
// of) OS error codes, should be added just above this comment.
|
||||
// `Other` and `Uncategorized` should remain at the end:
|
||||
//
|
||||
/// A custom error that does not fall under any other I/O error kind.
|
||||
///
|
||||
/// This can be used to construct your own errors 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,
|
||||
|
||||
/// 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 {
|
||||
pub(crate) const fn as_str(&self) -> &'static str {
|
||||
use ErrorKind::*;
|
||||
match *self {
|
||||
// tidy-alphabetical-start
|
||||
AddrInUse => "address in use",
|
||||
AddrNotAvailable => "address not available",
|
||||
AlreadyExists => "entity already exists",
|
||||
ArgumentListTooLong => "argument list too long",
|
||||
BrokenPipe => "broken pipe",
|
||||
ConnectionAborted => "connection aborted",
|
||||
ConnectionRefused => "connection refused",
|
||||
ConnectionReset => "connection reset",
|
||||
CrossesDevices => "cross-device link or rename",
|
||||
Deadlock => "deadlock",
|
||||
DirectoryNotEmpty => "directory not empty",
|
||||
ExecutableFileBusy => "executable file busy",
|
||||
FileTooLarge => "file too large",
|
||||
FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
|
||||
HostUnreachable => "host unreachable",
|
||||
InProgress => "in progress",
|
||||
Interrupted => "operation interrupted",
|
||||
InvalidData => "invalid data",
|
||||
InvalidFilename => "invalid filename",
|
||||
InvalidInput => "invalid input parameter",
|
||||
IsADirectory => "is a directory",
|
||||
NetworkDown => "network down",
|
||||
NetworkUnreachable => "network unreachable",
|
||||
NotADirectory => "not a directory",
|
||||
NotConnected => "not connected",
|
||||
NotFound => "entity not found",
|
||||
NotSeekable => "seek on unseekable file",
|
||||
Other => "other error",
|
||||
OutOfMemory => "out of memory",
|
||||
PermissionDenied => "permission denied",
|
||||
QuotaExceeded => "quota exceeded",
|
||||
ReadOnlyFilesystem => "read-only filesystem or storage medium",
|
||||
ResourceBusy => "resource busy",
|
||||
StaleNetworkFileHandle => "stale network file handle",
|
||||
StorageFull => "no storage space",
|
||||
TimedOut => "timed out",
|
||||
TooManyLinks => "too many links",
|
||||
Uncategorized => "uncategorized error",
|
||||
UnexpectedEof => "unexpected end of file",
|
||||
Unsupported => "unsupported",
|
||||
WouldBlock => "operation would block",
|
||||
WriteZero => "write zero",
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
}
|
||||
|
||||
// This compiles to the same code as the check+transmute, but doesn't require
|
||||
// unsafe, or to hard-code max ErrorKind or its size in a way the compiler
|
||||
// couldn't verify.
|
||||
#[inline]
|
||||
#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
pub const fn from_prim(ek: u32) -> Option<Self> {
|
||||
macro_rules! from_prim {
|
||||
($prim:expr => $Enum:ident { $($Variant:ident),* $(,)? }) => {{
|
||||
// Force a compile error if the list gets out of date.
|
||||
const _: fn(e: $Enum) = |e: $Enum| match e {
|
||||
$($Enum::$Variant => (),)*
|
||||
};
|
||||
match $prim {
|
||||
$(v if v == ($Enum::$Variant as _) => Some($Enum::$Variant),)*
|
||||
_ => None,
|
||||
}
|
||||
}}
|
||||
}
|
||||
from_prim!(ek => ErrorKind {
|
||||
NotFound,
|
||||
PermissionDenied,
|
||||
ConnectionRefused,
|
||||
ConnectionReset,
|
||||
HostUnreachable,
|
||||
NetworkUnreachable,
|
||||
ConnectionAborted,
|
||||
NotConnected,
|
||||
AddrInUse,
|
||||
AddrNotAvailable,
|
||||
NetworkDown,
|
||||
BrokenPipe,
|
||||
AlreadyExists,
|
||||
WouldBlock,
|
||||
NotADirectory,
|
||||
IsADirectory,
|
||||
DirectoryNotEmpty,
|
||||
ReadOnlyFilesystem,
|
||||
FilesystemLoop,
|
||||
StaleNetworkFileHandle,
|
||||
InvalidInput,
|
||||
InvalidData,
|
||||
TimedOut,
|
||||
WriteZero,
|
||||
StorageFull,
|
||||
NotSeekable,
|
||||
QuotaExceeded,
|
||||
FileTooLarge,
|
||||
ResourceBusy,
|
||||
ExecutableFileBusy,
|
||||
Deadlock,
|
||||
CrossesDevices,
|
||||
TooManyLinks,
|
||||
InvalidFilename,
|
||||
ArgumentListTooLong,
|
||||
Interrupted,
|
||||
Other,
|
||||
UnexpectedEof,
|
||||
Unsupported,
|
||||
OutOfMemory,
|
||||
InProgress,
|
||||
Uncategorized,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "io_errorkind_display", since = "1.60.0")]
|
||||
impl fmt::Display for ErrorKind {
|
||||
/// Shows a human-readable description of the `ErrorKind`.
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
//! Traits, helpers, and type definitions for core I/O functionality.
|
||||
|
||||
mod borrowed_buf;
|
||||
mod error;
|
||||
|
||||
#[unstable(feature = "core_io_borrowed_buf", issue = "117693")]
|
||||
pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor};
|
||||
#[unstable(feature = "core_io", issue = "154046")]
|
||||
pub use self::error::ErrorKind;
|
||||
|
||||
@@ -305,7 +305,7 @@ pub mod autodiff {
|
||||
pub mod cell;
|
||||
pub mod char;
|
||||
pub mod ffi;
|
||||
#[unstable(feature = "core_io_borrowed_buf", issue = "117693")]
|
||||
#[unstable(feature = "core_io", issue = "154046")]
|
||||
pub mod io;
|
||||
pub mod iter;
|
||||
pub mod net;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#![feature(const_unsigned_bigint_helpers)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_intrinsics_fallbacks)]
|
||||
#![feature(core_io)]
|
||||
#![feature(core_io_borrowed_buf)]
|
||||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
|
||||
+4
-318
@@ -1,6 +1,9 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::io::ErrorKind;
|
||||
|
||||
// On 64-bit platforms, `io::Error` may use a bit-packed representation to
|
||||
// reduce size. However, this representation assumes that error codes are
|
||||
// always 32-bit wide.
|
||||
@@ -206,323 +209,6 @@ struct Custom {
|
||||
error: Box<dyn error::Error + Send + Sync>,
|
||||
}
|
||||
|
||||
/// A list specifying general categories of I/O error.
|
||||
///
|
||||
/// This list is intended to grow over time and it is not recommended to
|
||||
/// exhaustively match against it.
|
||||
///
|
||||
/// It is used with the [`io::Error`] type.
|
||||
///
|
||||
/// [`io::Error`]: Error
|
||||
///
|
||||
/// # Handling errors and matching on `ErrorKind`
|
||||
///
|
||||
/// In application code, use `match` for the `ErrorKind` values you are
|
||||
/// expecting; use `_` to match "all other errors".
|
||||
///
|
||||
/// In comprehensive and thorough tests that want to verify that a test doesn't
|
||||
/// return any known incorrect error kind, you may want to cut-and-paste the
|
||||
/// current full list of errors from here into your test code, and then match
|
||||
/// `_` as the correct case. This seems counterintuitive, but it will make your
|
||||
/// tests more robust. In particular, if you want to verify that your code does
|
||||
/// produce an unrecognized error kind, the robust solution is to check for all
|
||||
/// the recognized error kinds and fail in those cases.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "io_errorkind")]
|
||||
#[allow(deprecated)]
|
||||
#[non_exhaustive]
|
||||
pub enum ErrorKind {
|
||||
/// An entity was not found, often a file.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
NotFound,
|
||||
/// The operation lacked the necessary privileges to complete.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
PermissionDenied,
|
||||
/// The connection was refused by the remote server.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
ConnectionRefused,
|
||||
/// The connection was reset by the remote server.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
ConnectionReset,
|
||||
/// The remote host is not reachable.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
HostUnreachable,
|
||||
/// The network containing the remote host is not reachable.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NetworkUnreachable,
|
||||
/// The connection was aborted (terminated) by the remote server.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
ConnectionAborted,
|
||||
/// The network operation failed because it was not connected yet.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
NotConnected,
|
||||
/// A socket address could not be bound because the address is already in
|
||||
/// use elsewhere.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
AddrInUse,
|
||||
/// A nonexistent interface was requested or the requested address was not
|
||||
/// local.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
AddrNotAvailable,
|
||||
/// The system's networking is down.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NetworkDown,
|
||||
/// The operation failed because a pipe was closed.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
BrokenPipe,
|
||||
/// An entity already exists, often a file.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
AlreadyExists,
|
||||
/// The operation needs to block to complete, but the blocking operation was
|
||||
/// requested to not occur.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
WouldBlock,
|
||||
/// A filesystem object is, unexpectedly, not a directory.
|
||||
///
|
||||
/// For example, a filesystem path was specified where one of the intermediate directory
|
||||
/// components was, in fact, a plain file.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NotADirectory,
|
||||
/// The filesystem object is, unexpectedly, a directory.
|
||||
///
|
||||
/// A directory was specified when a non-directory was expected.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
IsADirectory,
|
||||
/// A non-empty directory was specified where an empty directory was expected.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
DirectoryNotEmpty,
|
||||
/// The filesystem or storage medium is read-only, but a write operation was attempted.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ReadOnlyFilesystem,
|
||||
/// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
|
||||
///
|
||||
/// There was a loop (or excessively long chain) resolving a filesystem object
|
||||
/// or file IO object.
|
||||
///
|
||||
/// On Unix this is usually the result of a symbolic link loop; or, of exceeding the
|
||||
/// system-specific limit on the depth of symlink traversal.
|
||||
#[unstable(feature = "io_error_more", issue = "86442")]
|
||||
FilesystemLoop,
|
||||
/// Stale network file handle.
|
||||
///
|
||||
/// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
|
||||
/// by problems with the network or server.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
StaleNetworkFileHandle,
|
||||
/// A parameter was incorrect.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
InvalidInput,
|
||||
/// Data not valid for the operation were encountered.
|
||||
///
|
||||
/// Unlike [`InvalidInput`], this typically means that the operation
|
||||
/// parameters were valid, however the error was caused by malformed
|
||||
/// input data.
|
||||
///
|
||||
/// For example, a function that reads a file into a string will error with
|
||||
/// `InvalidData` if the file's contents are not valid UTF-8.
|
||||
///
|
||||
/// [`InvalidInput`]: ErrorKind::InvalidInput
|
||||
#[stable(feature = "io_invalid_data", since = "1.2.0")]
|
||||
InvalidData,
|
||||
/// The I/O operation's timeout expired, causing it to be canceled.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
TimedOut,
|
||||
/// An error returned when an operation could not be completed because a
|
||||
/// call to [`write`] returned [`Ok(0)`].
|
||||
///
|
||||
/// This typically means that an operation could only succeed if it wrote a
|
||||
/// particular number of bytes but only a smaller number of bytes could be
|
||||
/// written.
|
||||
///
|
||||
/// [`write`]: crate::io::Write::write
|
||||
/// [`Ok(0)`]: Ok
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
WriteZero,
|
||||
/// The underlying storage (typically, a filesystem) is full.
|
||||
///
|
||||
/// This does not include out of quota errors.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
StorageFull,
|
||||
/// Seek on unseekable file.
|
||||
///
|
||||
/// Seeking was attempted on an open file handle which is not suitable for seeking - for
|
||||
/// example, on Unix, a named pipe opened with `File::open`.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NotSeekable,
|
||||
/// Filesystem quota or some other kind of quota was exceeded.
|
||||
#[stable(feature = "io_error_quota_exceeded", since = "1.85.0")]
|
||||
QuotaExceeded,
|
||||
/// File larger than allowed or supported.
|
||||
///
|
||||
/// This might arise from a hard limit of the underlying filesystem or file access API, or from
|
||||
/// an administratively imposed resource limitation. Simple disk full, and out of quota, have
|
||||
/// their own errors.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
FileTooLarge,
|
||||
/// Resource is busy.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ResourceBusy,
|
||||
/// Executable file is busy.
|
||||
///
|
||||
/// An attempt was made to write to a file which is also in use as a running program. (Not all
|
||||
/// operating systems detect this situation.)
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ExecutableFileBusy,
|
||||
/// Deadlock (avoided).
|
||||
///
|
||||
/// A file locking operation would result in deadlock. This situation is typically detected, if
|
||||
/// at all, on a best-effort basis.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
Deadlock,
|
||||
/// Cross-device or cross-filesystem (hard) link or rename.
|
||||
#[stable(feature = "io_error_crosses_devices", since = "1.85.0")]
|
||||
CrossesDevices,
|
||||
/// Too many (hard) links to the same filesystem object.
|
||||
///
|
||||
/// The filesystem does not support making so many hardlinks to the same file.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
TooManyLinks,
|
||||
/// A filename was invalid.
|
||||
///
|
||||
/// This error can also occur if a length limit for a name was exceeded.
|
||||
#[stable(feature = "io_error_invalid_filename", since = "1.87.0")]
|
||||
InvalidFilename,
|
||||
/// Program argument list too long.
|
||||
///
|
||||
/// When trying to run an external program, a system or process limit on the size of the
|
||||
/// arguments would have been exceeded.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
ArgumentListTooLong,
|
||||
/// This operation was interrupted.
|
||||
///
|
||||
/// Interrupted operations can typically be retried.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Interrupted,
|
||||
|
||||
/// This operation is unsupported on this platform.
|
||||
///
|
||||
/// This means that the operation can never succeed.
|
||||
#[stable(feature = "unsupported_error", since = "1.53.0")]
|
||||
Unsupported,
|
||||
|
||||
// ErrorKinds which are primarily categorisations for OS error
|
||||
// codes should be added above.
|
||||
//
|
||||
/// An error returned when an operation could not be completed because an
|
||||
/// "end of file" was reached prematurely.
|
||||
///
|
||||
/// This typically means that an operation could only succeed if it read a
|
||||
/// particular number of bytes but only a smaller number of bytes could be
|
||||
/// read.
|
||||
#[stable(feature = "read_exact", since = "1.6.0")]
|
||||
UnexpectedEof,
|
||||
|
||||
/// An operation could not be completed, because it failed
|
||||
/// to allocate enough memory.
|
||||
#[stable(feature = "out_of_memory_error", since = "1.54.0")]
|
||||
OutOfMemory,
|
||||
|
||||
/// The operation was partially successful and needs to be checked
|
||||
/// later on due to not blocking.
|
||||
#[unstable(feature = "io_error_inprogress", issue = "130840")]
|
||||
InProgress,
|
||||
|
||||
// "Unusual" error kinds which do not correspond simply to (sets
|
||||
// of) OS error codes, should be added just above this comment.
|
||||
// `Other` and `Uncategorized` should remain at the end:
|
||||
//
|
||||
/// A custom error that does not fall under any other I/O error kind.
|
||||
///
|
||||
/// 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,
|
||||
|
||||
/// 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 {
|
||||
pub(crate) fn as_str(&self) -> &'static str {
|
||||
use ErrorKind::*;
|
||||
match *self {
|
||||
// tidy-alphabetical-start
|
||||
AddrInUse => "address in use",
|
||||
AddrNotAvailable => "address not available",
|
||||
AlreadyExists => "entity already exists",
|
||||
ArgumentListTooLong => "argument list too long",
|
||||
BrokenPipe => "broken pipe",
|
||||
ConnectionAborted => "connection aborted",
|
||||
ConnectionRefused => "connection refused",
|
||||
ConnectionReset => "connection reset",
|
||||
CrossesDevices => "cross-device link or rename",
|
||||
Deadlock => "deadlock",
|
||||
DirectoryNotEmpty => "directory not empty",
|
||||
ExecutableFileBusy => "executable file busy",
|
||||
FileTooLarge => "file too large",
|
||||
FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
|
||||
HostUnreachable => "host unreachable",
|
||||
InProgress => "in progress",
|
||||
Interrupted => "operation interrupted",
|
||||
InvalidData => "invalid data",
|
||||
InvalidFilename => "invalid filename",
|
||||
InvalidInput => "invalid input parameter",
|
||||
IsADirectory => "is a directory",
|
||||
NetworkDown => "network down",
|
||||
NetworkUnreachable => "network unreachable",
|
||||
NotADirectory => "not a directory",
|
||||
NotConnected => "not connected",
|
||||
NotFound => "entity not found",
|
||||
NotSeekable => "seek on unseekable file",
|
||||
Other => "other error",
|
||||
OutOfMemory => "out of memory",
|
||||
PermissionDenied => "permission denied",
|
||||
QuotaExceeded => "quota exceeded",
|
||||
ReadOnlyFilesystem => "read-only filesystem or storage medium",
|
||||
ResourceBusy => "resource busy",
|
||||
StaleNetworkFileHandle => "stale network file handle",
|
||||
StorageFull => "no storage space",
|
||||
TimedOut => "timed out",
|
||||
TooManyLinks => "too many links",
|
||||
Uncategorized => "uncategorized error",
|
||||
UnexpectedEof => "unexpected end of file",
|
||||
Unsupported => "unsupported",
|
||||
WouldBlock => "operation would block",
|
||||
WriteZero => "write zero",
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "io_errorkind_display", since = "1.60.0")]
|
||||
impl fmt::Display for ErrorKind {
|
||||
/// Shows a human-readable description of the `ErrorKind`.
|
||||
///
|
||||
/// This is similar to `impl Display for Error`, but doesn't require first converting to Error.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use std::io::ErrorKind;
|
||||
/// assert_eq!("entity not found", ErrorKind::NotFound.to_string());
|
||||
/// ```
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
/// Intended for use for errors not exposed to the user, where allocating onto
|
||||
/// the heap (for normal construction via Error::new) is too costly.
|
||||
#[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
|
||||
@@ -1051,7 +737,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "{detail} (os error {code})")
|
||||
}
|
||||
ErrorData::Custom(ref c) => c.error.fmt(fmt),
|
||||
ErrorData::Simple(kind) => write!(fmt, "{}", kind.as_str()),
|
||||
ErrorData::Simple(kind) => kind.fmt(fmt),
|
||||
ErrorData::SimpleMessage(msg) => msg.message.fmt(fmt),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ unsafe fn decode_repr<C, F>(ptr: NonNull<()>, make_custom: F) -> ErrorData<C>
|
||||
}
|
||||
TAG_SIMPLE => {
|
||||
let kind_bits = (bits >> 32) as u32;
|
||||
let kind = kind_from_prim(kind_bits).unwrap_or_else(|| {
|
||||
let kind = ErrorKind::from_prim(kind_bits).unwrap_or_else(|| {
|
||||
debug_assert!(false, "Invalid io::error::Repr bits: `Repr({:#018x})`", bits);
|
||||
// This means the `ptr` passed in was not valid, which violates
|
||||
// the unsafe contract of `decode_repr`.
|
||||
@@ -283,69 +283,6 @@ unsafe fn decode_repr<C, F>(ptr: NonNull<()>, make_custom: F) -> ErrorData<C>
|
||||
}
|
||||
}
|
||||
|
||||
// This compiles to the same code as the check+transmute, but doesn't require
|
||||
// unsafe, or to hard-code max ErrorKind or its size in a way the compiler
|
||||
// couldn't verify.
|
||||
#[inline]
|
||||
fn kind_from_prim(ek: u32) -> Option<ErrorKind> {
|
||||
macro_rules! from_prim {
|
||||
($prim:expr => $Enum:ident { $($Variant:ident),* $(,)? }) => {{
|
||||
// Force a compile error if the list gets out of date.
|
||||
const _: fn(e: $Enum) = |e: $Enum| match e {
|
||||
$($Enum::$Variant => ()),*
|
||||
};
|
||||
match $prim {
|
||||
$(v if v == ($Enum::$Variant as _) => Some($Enum::$Variant),)*
|
||||
_ => None,
|
||||
}
|
||||
}}
|
||||
}
|
||||
from_prim!(ek => ErrorKind {
|
||||
NotFound,
|
||||
PermissionDenied,
|
||||
ConnectionRefused,
|
||||
ConnectionReset,
|
||||
HostUnreachable,
|
||||
NetworkUnreachable,
|
||||
ConnectionAborted,
|
||||
NotConnected,
|
||||
AddrInUse,
|
||||
AddrNotAvailable,
|
||||
NetworkDown,
|
||||
BrokenPipe,
|
||||
AlreadyExists,
|
||||
WouldBlock,
|
||||
NotADirectory,
|
||||
IsADirectory,
|
||||
DirectoryNotEmpty,
|
||||
ReadOnlyFilesystem,
|
||||
FilesystemLoop,
|
||||
StaleNetworkFileHandle,
|
||||
InvalidInput,
|
||||
InvalidData,
|
||||
TimedOut,
|
||||
WriteZero,
|
||||
StorageFull,
|
||||
NotSeekable,
|
||||
QuotaExceeded,
|
||||
FileTooLarge,
|
||||
ResourceBusy,
|
||||
ExecutableFileBusy,
|
||||
Deadlock,
|
||||
CrossesDevices,
|
||||
TooManyLinks,
|
||||
InvalidFilename,
|
||||
ArgumentListTooLong,
|
||||
Interrupted,
|
||||
Other,
|
||||
UnexpectedEof,
|
||||
Unsupported,
|
||||
OutOfMemory,
|
||||
InProgress,
|
||||
Uncategorized,
|
||||
})
|
||||
}
|
||||
|
||||
// Some static checking to alert us if a change breaks any of the assumptions
|
||||
// that our encoding relies on for correctness and soundness. (Some of these are
|
||||
// a bit overly thorough/cautious, admittedly)
|
||||
|
||||
@@ -321,7 +321,9 @@
|
||||
#![feature(const_default)]
|
||||
#![feature(core_float_math)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_io)]
|
||||
#![feature(core_io_borrowed_buf)]
|
||||
#![feature(core_io_internals)]
|
||||
#![feature(cstr_display)]
|
||||
#![feature(drop_guard)]
|
||||
#![feature(duration_constants)]
|
||||
@@ -344,6 +346,9 @@
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(hint_must_use)]
|
||||
#![feature(int_from_ascii)]
|
||||
#![feature(io_error_inprogress)]
|
||||
#![feature(io_error_more)]
|
||||
#![feature(io_error_uncategorized)]
|
||||
#![feature(ip)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_next_chunk)]
|
||||
|
||||
@@ -60,6 +60,6 @@ pub fn error_string(errno: i32) -> String {
|
||||
} else if ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&errno) {
|
||||
format!("user-specified error {errno:08x}")
|
||||
} else {
|
||||
decode_error_kind(errno).as_str().into()
|
||||
format!("{}", decode_error_kind(errno))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//@ has deprecated/struct.A.html '//a[@href="{{channel}}/core/ops/range/struct.Range.html#structfield.start"]' 'start'
|
||||
//@ has deprecated/struct.B1.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
|
||||
//@ has deprecated/struct.B2.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
|
||||
//@ has deprecated/struct.B1.html '//a[@href="{{channel}}/core/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
|
||||
//@ has deprecated/struct.B2.html '//a[@href="{{channel}}/core/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
|
||||
|
||||
#[deprecated = "[start][std::ops::Range::start]"]
|
||||
pub struct A;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//@ has field/index.html '//a[@href="{{channel}}/core/ops/range/struct.Range.html#structfield.start"]' 'start'
|
||||
//@ has field/index.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
|
||||
//@ has field/index.html '//a[@href="{{channel}}/core/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
|
||||
//@ has field/index.html '//a[@href="struct.FieldAndMethod.html#structfield.x"]' 'x'
|
||||
//@ has field/index.html '//a[@href="enum.VariantAndMethod.html#variant.X"]' 'X'
|
||||
//! [start][std::ops::Range::start]
|
||||
//! [not_found][std::io::ErrorKind::NotFound]
|
||||
//! [not_found][core::io::ErrorKind::NotFound]
|
||||
//! [x][field@crate::FieldAndMethod::x]
|
||||
//! [X][variant@crate::VariantAndMethod::X]
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Ensure `ErrorKind` from `core` is gated behind `core_io`
|
||||
//@ edition:2024
|
||||
|
||||
use std::io::ErrorKind as ErrorKindFromStd;
|
||||
|
||||
use core::io::ErrorKind as ErrorKindFromCore;
|
||||
//~^ ERROR use of unstable library feature `core_io`
|
||||
|
||||
// Asserting both ErrorKinds are the same.
|
||||
const _: [ErrorKindFromCore; 1] = [ErrorKindFromStd::Other];
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,13 @@
|
||||
error[E0658]: use of unstable library feature `core_io`
|
||||
--> $DIR/feature-gate-io_error_kind_in_core.rs:6:5
|
||||
|
|
||||
LL | use core::io::ErrorKind as ErrorKindFromCore;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #154046 <https://github.com/rust-lang/rust/issues/154046> for more information
|
||||
= help: add `#![feature(core_io)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
Reference in New Issue
Block a user