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}