Skip to main content

core/io/
error.rs

1#![unstable(feature = "core_io", issue = "154046")]
2
3use crate::fmt;
4
5/// The type of raw OS error codes.
6///
7/// This is an [`i32`] on all currently supported platforms, but platforms
8/// added in the future (such as UEFI) may use a different primitive type like
9/// [`usize`]. Use `as` or [`into`] conversions where applicable to ensure maximum
10/// portability.
11///
12/// [`into`]: Into::into
13#[unstable(feature = "raw_os_error_ty", issue = "107792")]
14pub type RawOsError = cfg_select! {
15    target_os = "uefi" => usize,
16    _ => i32,
17};
18
19/// A list specifying general categories of I/O error.
20///
21/// This list is intended to grow over time and it is not recommended to
22/// exhaustively match against it.
23///
24/// # Handling errors and matching on `ErrorKind`
25///
26/// In application code, use `match` for the `ErrorKind` values you are
27/// expecting; use `_` to match "all other errors".
28///
29/// In comprehensive and thorough tests that want to verify that a test doesn't
30/// return any known incorrect error kind, you may want to cut-and-paste the
31/// current full list of errors from here into your test code, and then match
32/// `_` as the correct case. This seems counterintuitive, but it will make your
33/// tests more robust. In particular, if you want to verify that your code does
34/// produce an unrecognized error kind, the robust solution is to check for all
35/// the recognized error kinds and fail in those cases.
36#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
37#[stable(feature = "rust1", since = "1.0.0")]
38#[cfg_attr(not(test), rustc_diagnostic_item = "io_errorkind")]
39#[allow(deprecated)]
40#[non_exhaustive]
41pub enum ErrorKind {
42    /// An entity was not found, often a file.
43    #[stable(feature = "rust1", since = "1.0.0")]
44    NotFound,
45    /// The operation lacked the necessary privileges to complete.
46    #[stable(feature = "rust1", since = "1.0.0")]
47    PermissionDenied,
48    /// The connection was refused by the remote server.
49    #[stable(feature = "rust1", since = "1.0.0")]
50    ConnectionRefused,
51    /// The connection was reset by the remote server.
52    #[stable(feature = "rust1", since = "1.0.0")]
53    ConnectionReset,
54    /// The remote host is not reachable.
55    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
56    HostUnreachable,
57    /// The network containing the remote host is not reachable.
58    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
59    NetworkUnreachable,
60    /// The connection was aborted (terminated) by the remote server.
61    #[stable(feature = "rust1", since = "1.0.0")]
62    ConnectionAborted,
63    /// The network operation failed because it was not connected yet.
64    #[stable(feature = "rust1", since = "1.0.0")]
65    NotConnected,
66    /// A socket address could not be bound because the address is already in
67    /// use elsewhere.
68    #[stable(feature = "rust1", since = "1.0.0")]
69    AddrInUse,
70    /// A nonexistent interface was requested or the requested address was not
71    /// local.
72    #[stable(feature = "rust1", since = "1.0.0")]
73    AddrNotAvailable,
74    /// The system's networking is down.
75    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
76    NetworkDown,
77    /// The operation failed because a pipe was closed.
78    #[stable(feature = "rust1", since = "1.0.0")]
79    BrokenPipe,
80    /// An entity already exists, often a file.
81    #[stable(feature = "rust1", since = "1.0.0")]
82    AlreadyExists,
83    /// The operation needs to block to complete, but the blocking operation was
84    /// requested to not occur.
85    #[stable(feature = "rust1", since = "1.0.0")]
86    WouldBlock,
87    /// A filesystem object is, unexpectedly, not a directory.
88    ///
89    /// For example, a filesystem path was specified where one of the intermediate directory
90    /// components was, in fact, a plain file.
91    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
92    NotADirectory,
93    /// The filesystem object is, unexpectedly, a directory.
94    ///
95    /// A directory was specified when a non-directory was expected.
96    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
97    IsADirectory,
98    /// A non-empty directory was specified where an empty directory was expected.
99    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
100    DirectoryNotEmpty,
101    /// The filesystem or storage medium is read-only, but a write operation was attempted.
102    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
103    ReadOnlyFilesystem,
104    /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
105    ///
106    /// There was a loop (or excessively long chain) resolving a filesystem object
107    /// or file IO object.
108    ///
109    /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the
110    /// system-specific limit on the depth of symlink traversal.
111    #[unstable(feature = "io_error_more", issue = "86442")]
112    FilesystemLoop,
113    /// Stale network file handle.
114    ///
115    /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
116    /// by problems with the network or server.
117    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
118    StaleNetworkFileHandle,
119    /// A parameter was incorrect.
120    #[stable(feature = "rust1", since = "1.0.0")]
121    InvalidInput,
122    /// Data not valid for the operation were encountered.
123    ///
124    /// Unlike [`InvalidInput`], this typically means that the operation
125    /// parameters were valid, however the error was caused by malformed
126    /// input data.
127    ///
128    /// For example, a function that reads a file into a string will error with
129    /// `InvalidData` if the file's contents are not valid UTF-8.
130    ///
131    /// [`InvalidInput`]: ErrorKind::InvalidInput
132    #[stable(feature = "io_invalid_data", since = "1.2.0")]
133    InvalidData,
134    /// The I/O operation's timeout expired, causing it to be canceled.
135    #[stable(feature = "rust1", since = "1.0.0")]
136    TimedOut,
137    /// An error returned when an operation could not be completed because a
138    /// call to an underlying writer returned [`Ok(0)`].
139    ///
140    /// This typically means that an operation could only succeed if it wrote a
141    /// particular number of bytes but only a smaller number of bytes could be
142    /// written.
143    ///
144    /// [`Ok(0)`]: Ok
145    #[stable(feature = "rust1", since = "1.0.0")]
146    WriteZero,
147    /// The underlying storage (typically, a filesystem) is full.
148    ///
149    /// This does not include out of quota errors.
150    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
151    StorageFull,
152    /// Seek on unseekable file.
153    ///
154    /// Seeking was attempted on an open file handle which is not suitable for seeking - for
155    /// example, on Unix, a named pipe opened with `File::open`.
156    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
157    NotSeekable,
158    /// Filesystem quota or some other kind of quota was exceeded.
159    #[stable(feature = "io_error_quota_exceeded", since = "1.85.0")]
160    QuotaExceeded,
161    /// File larger than allowed or supported.
162    ///
163    /// This might arise from a hard limit of the underlying filesystem or file access API, or from
164    /// an administratively imposed resource limitation.  Simple disk full, and out of quota, have
165    /// their own errors.
166    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
167    FileTooLarge,
168    /// Resource is busy.
169    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
170    ResourceBusy,
171    /// Executable file is busy.
172    ///
173    /// An attempt was made to write to a file which is also in use as a running program.  (Not all
174    /// operating systems detect this situation.)
175    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
176    ExecutableFileBusy,
177    /// Deadlock (avoided).
178    ///
179    /// A file locking operation would result in deadlock.  This situation is typically detected, if
180    /// at all, on a best-effort basis.
181    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
182    Deadlock,
183    /// Cross-device or cross-filesystem (hard) link or rename.
184    #[stable(feature = "io_error_crosses_devices", since = "1.85.0")]
185    CrossesDevices,
186    /// Too many (hard) links to the same filesystem object.
187    ///
188    /// The filesystem does not support making so many hardlinks to the same file.
189    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
190    TooManyLinks,
191    /// A filename was invalid.
192    ///
193    /// This error can also occur if a length limit for a name was exceeded.
194    #[stable(feature = "io_error_invalid_filename", since = "1.87.0")]
195    InvalidFilename,
196    /// Program argument list too long.
197    ///
198    /// When trying to run an external program, a system or process limit on the size of the
199    /// arguments would have been exceeded.
200    #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
201    ArgumentListTooLong,
202    /// This operation was interrupted.
203    ///
204    /// Interrupted operations can typically be retried.
205    #[stable(feature = "rust1", since = "1.0.0")]
206    Interrupted,
207
208    /// This operation is unsupported on this platform.
209    ///
210    /// This means that the operation can never succeed.
211    #[stable(feature = "unsupported_error", since = "1.53.0")]
212    Unsupported,
213
214    // ErrorKinds which are primarily categorisations for OS error
215    // codes should be added above.
216    //
217    /// An error returned when an operation could not be completed because an
218    /// "end of file" was reached prematurely.
219    ///
220    /// This typically means that an operation could only succeed if it read a
221    /// particular number of bytes but only a smaller number of bytes could be
222    /// read.
223    #[stable(feature = "read_exact", since = "1.6.0")]
224    UnexpectedEof,
225
226    /// An operation could not be completed, because it failed
227    /// to allocate enough memory.
228    #[stable(feature = "out_of_memory_error", since = "1.54.0")]
229    OutOfMemory,
230
231    /// The operation was partially successful and needs to be checked
232    /// later on due to not blocking.
233    #[unstable(feature = "io_error_inprogress", issue = "130840")]
234    InProgress,
235
236    // "Unusual" error kinds which do not correspond simply to (sets
237    // of) OS error codes, should be added just above this comment.
238    // `Other` and `Uncategorized` should remain at the end:
239    //
240    /// A custom error that does not fall under any other I/O error kind.
241    ///
242    /// This can be used to construct your own errors that do not match any
243    /// [`ErrorKind`].
244    ///
245    /// This [`ErrorKind`] is not used by the standard library.
246    ///
247    /// Errors from the standard library that do not fall under any of the I/O
248    /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
249    /// New [`ErrorKind`]s might be added in the future for some of those.
250    #[stable(feature = "rust1", since = "1.0.0")]
251    Other,
252
253    /// Any I/O error from the standard library that's not part of this list.
254    ///
255    /// Errors that are `Uncategorized` now may move to a different or a new
256    /// [`ErrorKind`] variant in the future. It is not recommended to match
257    /// an error against `Uncategorized`; use a wildcard match (`_`) instead.
258    #[unstable(feature = "io_error_uncategorized", issue = "none")]
259    #[doc(hidden)]
260    Uncategorized,
261}
262
263impl ErrorKind {
264    pub(crate) const fn as_str(&self) -> &'static str {
265        use ErrorKind::*;
266        match *self {
267            // tidy-alphabetical-start
268            AddrInUse => "address in use",
269            AddrNotAvailable => "address not available",
270            AlreadyExists => "entity already exists",
271            ArgumentListTooLong => "argument list too long",
272            BrokenPipe => "broken pipe",
273            ConnectionAborted => "connection aborted",
274            ConnectionRefused => "connection refused",
275            ConnectionReset => "connection reset",
276            CrossesDevices => "cross-device link or rename",
277            Deadlock => "deadlock",
278            DirectoryNotEmpty => "directory not empty",
279            ExecutableFileBusy => "executable file busy",
280            FileTooLarge => "file too large",
281            FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
282            HostUnreachable => "host unreachable",
283            InProgress => "in progress",
284            Interrupted => "operation interrupted",
285            InvalidData => "invalid data",
286            InvalidFilename => "invalid filename",
287            InvalidInput => "invalid input parameter",
288            IsADirectory => "is a directory",
289            NetworkDown => "network down",
290            NetworkUnreachable => "network unreachable",
291            NotADirectory => "not a directory",
292            NotConnected => "not connected",
293            NotFound => "entity not found",
294            NotSeekable => "seek on unseekable file",
295            Other => "other error",
296            OutOfMemory => "out of memory",
297            PermissionDenied => "permission denied",
298            QuotaExceeded => "quota exceeded",
299            ReadOnlyFilesystem => "read-only filesystem or storage medium",
300            ResourceBusy => "resource busy",
301            StaleNetworkFileHandle => "stale network file handle",
302            StorageFull => "no storage space",
303            TimedOut => "timed out",
304            TooManyLinks => "too many links",
305            Uncategorized => "uncategorized error",
306            UnexpectedEof => "unexpected end of file",
307            Unsupported => "unsupported",
308            WouldBlock => "operation would block",
309            WriteZero => "write zero",
310            // tidy-alphabetical-end
311        }
312    }
313
314    // This compiles to the same code as the check+transmute, but doesn't require
315    // unsafe, or to hard-code max ErrorKind or its size in a way the compiler
316    // couldn't verify.
317    #[inline]
318    #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
319    #[doc(hidden)]
320    pub const fn from_prim(ek: u32) -> Option<Self> {
321        macro_rules! from_prim {
322            ($prim:expr => $Enum:ident { $($Variant:ident),* $(,)? }) => {{
323                // Force a compile error if the list gets out of date.
324                const _: fn(e: $Enum) = |e: $Enum| match e {
325                    $($Enum::$Variant => (),)*
326                };
327                match $prim {
328                    $(v if v == ($Enum::$Variant as _) => Some($Enum::$Variant),)*
329                    _ => None,
330                }
331            }}
332        }
333        from_prim!(ek => ErrorKind {
334            NotFound,
335            PermissionDenied,
336            ConnectionRefused,
337            ConnectionReset,
338            HostUnreachable,
339            NetworkUnreachable,
340            ConnectionAborted,
341            NotConnected,
342            AddrInUse,
343            AddrNotAvailable,
344            NetworkDown,
345            BrokenPipe,
346            AlreadyExists,
347            WouldBlock,
348            NotADirectory,
349            IsADirectory,
350            DirectoryNotEmpty,
351            ReadOnlyFilesystem,
352            FilesystemLoop,
353            StaleNetworkFileHandle,
354            InvalidInput,
355            InvalidData,
356            TimedOut,
357            WriteZero,
358            StorageFull,
359            NotSeekable,
360            QuotaExceeded,
361            FileTooLarge,
362            ResourceBusy,
363            ExecutableFileBusy,
364            Deadlock,
365            CrossesDevices,
366            TooManyLinks,
367            InvalidFilename,
368            ArgumentListTooLong,
369            Interrupted,
370            Other,
371            UnexpectedEof,
372            Unsupported,
373            OutOfMemory,
374            InProgress,
375            Uncategorized,
376        })
377    }
378}
379
380#[stable(feature = "io_errorkind_display", since = "1.60.0")]
381impl fmt::Display for ErrorKind {
382    /// Shows a human-readable description of the `ErrorKind`.
383    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
384        fmt.write_str(self.as_str())
385    }
386}