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