std/io/error.rs
1#[cfg(test)]
2mod tests;
3
4#[cfg(all(target_pointer_width = "64", not(target_os = "uefi")))]
5mod repr_bitpacked;
6#[cfg(all(target_pointer_width = "64", not(target_os = "uefi")))]
7use repr_bitpacked::Repr;
8
9#[cfg(any(not(target_pointer_width = "64"), target_os = "uefi"))]
10mod repr_unpacked;
11#[cfg(any(not(target_pointer_width = "64"), target_os = "uefi"))]
12use repr_unpacked::Repr;
13
14use crate::{error, fmt, result, sys};
15
16/// A specialized [`Result`] type for I/O operations.
17///
18/// This type is broadly used across [`std::io`] for any operation which may
19/// produce an error.
20///
21/// This typedef is generally used to avoid writing out [`io::Error`] directly and
22/// is otherwise a direct mapping to [`Result`].
23///
24/// While usual Rust style is to import types directly, aliases of [`Result`]
25/// often are not, to make it easier to distinguish between them. [`Result`] is
26/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
27/// will generally use `io::Result` instead of shadowing the [prelude]'s import
28/// of [`std::result::Result`][`Result`].
29///
30/// [`std::io`]: crate::io
31/// [`io::Error`]: Error
32/// [`Result`]: crate::result::Result
33/// [prelude]: crate::prelude
34///
35/// # Examples
36///
37/// A convenience function that bubbles an `io::Result` to its caller:
38///
39/// ```
40/// use std::io;
41///
42/// fn get_string() -> io::Result<String> {
43/// let mut buffer = String::new();
44///
45/// io::stdin().read_line(&mut buffer)?;
46///
47/// Ok(buffer)
48/// }
49/// ```
50#[stable(feature = "rust1", since = "1.0.0")]
51#[doc(search_unbox)]
52pub type Result<T> = result::Result<T, Error>;
53
54/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
55/// associated traits.
56///
57/// Errors mostly originate from the underlying OS, but custom instances of
58/// `Error` can be created with crafted error messages and a particular value of
59/// [`ErrorKind`].
60///
61/// [`Read`]: crate::io::Read
62/// [`Write`]: crate::io::Write
63/// [`Seek`]: crate::io::Seek
64#[stable(feature = "rust1", since = "1.0.0")]
65pub struct Error {
66 repr: Repr,
67}
68
69#[stable(feature = "rust1", since = "1.0.0")]
70impl fmt::Debug for Error {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 fmt::Debug::fmt(&self.repr, f)
73 }
74}
75
76/// Common errors constants for use in std
77#[allow(dead_code)]
78impl Error {
79 pub(crate) const INVALID_UTF8: Self =
80 const_error!(ErrorKind::InvalidData, "stream did not contain valid UTF-8");
81
82 pub(crate) const READ_EXACT_EOF: Self =
83 const_error!(ErrorKind::UnexpectedEof, "failed to fill whole buffer");
84
85 pub(crate) const UNKNOWN_THREAD_COUNT: Self = const_error!(
86 ErrorKind::NotFound,
87 "the number of hardware threads is not known for the target platform",
88 );
89
90 pub(crate) const UNSUPPORTED_PLATFORM: Self =
91 const_error!(ErrorKind::Unsupported, "operation not supported on this platform");
92
93 pub(crate) const WRITE_ALL_EOF: Self =
94 const_error!(ErrorKind::WriteZero, "failed to write whole buffer");
95
96 pub(crate) const ZERO_TIMEOUT: Self =
97 const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout");
98}
99
100#[stable(feature = "rust1", since = "1.0.0")]
101impl From<alloc::ffi::NulError> for Error {
102 /// Converts a [`alloc::ffi::NulError`] into a [`Error`].
103 fn from(_: alloc::ffi::NulError) -> Error {
104 const_error!(ErrorKind::InvalidInput, "data provided contains a nul byte")
105 }
106}
107
108#[stable(feature = "io_error_from_try_reserve", since = "1.78.0")]
109impl From<alloc::collections::TryReserveError> for Error {
110 /// Converts `TryReserveError` to an error with [`ErrorKind::OutOfMemory`].
111 ///
112 /// `TryReserveError` won't be available as the error `source()`,
113 /// but this may change in the future.
114 fn from(_: alloc::collections::TryReserveError) -> Error {
115 // ErrorData::Custom allocates, which isn't great for handling OOM errors.
116 ErrorKind::OutOfMemory.into()
117 }
118}
119
120// Only derive debug in tests, to make sure it
121// doesn't accidentally get printed.
122#[cfg_attr(test, derive(Debug))]
123enum ErrorData<C> {
124 Os(RawOsError),
125 Simple(ErrorKind),
126 SimpleMessage(&'static SimpleMessage),
127 Custom(C),
128}
129
130/// The type of raw OS error codes returned by [`Error::raw_os_error`].
131///
132/// This is an [`i32`] on all currently supported platforms, but platforms
133/// added in the future (such as UEFI) may use a different primitive type like
134/// [`usize`]. Use `as`or [`into`] conversions where applicable to ensure maximum
135/// portability.
136///
137/// [`into`]: Into::into
138#[unstable(feature = "raw_os_error_ty", issue = "107792")]
139pub type RawOsError = sys::RawOsError;
140
141// `#[repr(align(4))]` is probably redundant, it should have that value or
142// higher already. We include it just because repr_bitpacked.rs's encoding
143// requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the
144// alignment required by the struct, only increase it).
145//
146// If we add more variants to ErrorData, this can be increased to 8, but it
147// should probably be behind `#[cfg_attr(target_pointer_width = "64", ...)]` or
148// whatever cfg we're using to enable the `repr_bitpacked` code, since only the
149// that version needs the alignment, and 8 is higher than the alignment we'll
150// have on 32 bit platforms.
151//
152// (For the sake of being explicit: the alignment requirement here only matters
153// if `error/repr_bitpacked.rs` is in use — for the unpacked repr it doesn't
154// matter at all)
155#[doc(hidden)]
156#[unstable(feature = "io_const_error_internals", issue = "none")]
157#[repr(align(4))]
158#[derive(Debug)]
159pub struct SimpleMessage {
160 pub kind: ErrorKind,
161 pub message: &'static str,
162}
163
164/// Creates a new I/O error from a known kind of error and a string literal.
165///
166/// Contrary to [`Error::new`], this macro does not allocate and can be used in
167/// `const` contexts.
168///
169/// # Example
170/// ```
171/// #![feature(io_const_error)]
172/// use std::io::{const_error, Error, ErrorKind};
173///
174/// const FAIL: Error = const_error!(ErrorKind::Unsupported, "tried something that never works");
175///
176/// fn not_here() -> Result<(), Error> {
177/// Err(FAIL)
178/// }
179/// ```
180#[rustc_macro_transparency = "semitransparent"]
181#[unstable(feature = "io_const_error", issue = "133448")]
182#[allow_internal_unstable(hint_must_use, io_const_error_internals)]
183pub macro const_error($kind:expr, $message:expr $(,)?) {
184 $crate::hint::must_use($crate::io::Error::from_static_message(
185 const { &$crate::io::SimpleMessage { kind: $kind, message: $message } },
186 ))
187}
188
189// As with `SimpleMessage`: `#[repr(align(4))]` here is just because
190// repr_bitpacked's encoding requires it. In practice it almost certainly be
191// already be this high or higher.
192#[derive(Debug)]
193#[repr(align(4))]
194struct Custom {
195 kind: ErrorKind,
196 error: Box<dyn error::Error + Send + Sync>,
197}
198
199/// A list specifying general categories of I/O error.
200///
201/// This list is intended to grow over time and it is not recommended to
202/// exhaustively match against it.
203///
204/// It is used with the [`io::Error`] type.
205///
206/// [`io::Error`]: Error
207///
208/// # Handling errors and matching on `ErrorKind`
209///
210/// In application code, use `match` for the `ErrorKind` values you are
211/// expecting; use `_` to match "all other errors".
212///
213/// In comprehensive and thorough tests that want to verify that a test doesn't
214/// return any known incorrect error kind, you may want to cut-and-paste the
215/// current full list of errors from here into your test code, and then match
216/// `_` as the correct case. This seems counterintuitive, but it will make your
217/// tests more robust. In particular, if you want to verify that your code does
218/// produce an unrecognized error kind, the robust solution is to check for all
219/// the recognized error kinds and fail in those cases.
220#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
221#[stable(feature = "rust1", since = "1.0.0")]
222#[cfg_attr(not(test), rustc_diagnostic_item = "io_errorkind")]
223#[allow(deprecated)]
224#[non_exhaustive]
225pub enum ErrorKind {
226 /// An entity was not found, often a file.
227 #[stable(feature = "rust1", since = "1.0.0")]
228 NotFound,
229 /// The operation lacked the necessary privileges to complete.
230 #[stable(feature = "rust1", since = "1.0.0")]
231 PermissionDenied,
232 /// The connection was refused by the remote server.
233 #[stable(feature = "rust1", since = "1.0.0")]
234 ConnectionRefused,
235 /// The connection was reset by the remote server.
236 #[stable(feature = "rust1", since = "1.0.0")]
237 ConnectionReset,
238 /// The remote host is not reachable.
239 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
240 HostUnreachable,
241 /// The network containing the remote host is not reachable.
242 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
243 NetworkUnreachable,
244 /// The connection was aborted (terminated) by the remote server.
245 #[stable(feature = "rust1", since = "1.0.0")]
246 ConnectionAborted,
247 /// The network operation failed because it was not connected yet.
248 #[stable(feature = "rust1", since = "1.0.0")]
249 NotConnected,
250 /// A socket address could not be bound because the address is already in
251 /// use elsewhere.
252 #[stable(feature = "rust1", since = "1.0.0")]
253 AddrInUse,
254 /// A nonexistent interface was requested or the requested address was not
255 /// local.
256 #[stable(feature = "rust1", since = "1.0.0")]
257 AddrNotAvailable,
258 /// The system's networking is down.
259 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
260 NetworkDown,
261 /// The operation failed because a pipe was closed.
262 #[stable(feature = "rust1", since = "1.0.0")]
263 BrokenPipe,
264 /// An entity already exists, often a file.
265 #[stable(feature = "rust1", since = "1.0.0")]
266 AlreadyExists,
267 /// The operation needs to block to complete, but the blocking operation was
268 /// requested to not occur.
269 #[stable(feature = "rust1", since = "1.0.0")]
270 WouldBlock,
271 /// A filesystem object is, unexpectedly, not a directory.
272 ///
273 /// For example, a filesystem path was specified where one of the intermediate directory
274 /// components was, in fact, a plain file.
275 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
276 NotADirectory,
277 /// The filesystem object is, unexpectedly, a directory.
278 ///
279 /// A directory was specified when a non-directory was expected.
280 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
281 IsADirectory,
282 /// A non-empty directory was specified where an empty directory was expected.
283 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
284 DirectoryNotEmpty,
285 /// The filesystem or storage medium is read-only, but a write operation was attempted.
286 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
287 ReadOnlyFilesystem,
288 /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
289 ///
290 /// There was a loop (or excessively long chain) resolving a filesystem object
291 /// or file IO object.
292 ///
293 /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the
294 /// system-specific limit on the depth of symlink traversal.
295 #[unstable(feature = "io_error_more", issue = "86442")]
296 FilesystemLoop,
297 /// Stale network file handle.
298 ///
299 /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
300 /// by problems with the network or server.
301 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
302 StaleNetworkFileHandle,
303 /// A parameter was incorrect.
304 #[stable(feature = "rust1", since = "1.0.0")]
305 InvalidInput,
306 /// Data not valid for the operation were encountered.
307 ///
308 /// Unlike [`InvalidInput`], this typically means that the operation
309 /// parameters were valid, however the error was caused by malformed
310 /// input data.
311 ///
312 /// For example, a function that reads a file into a string will error with
313 /// `InvalidData` if the file's contents are not valid UTF-8.
314 ///
315 /// [`InvalidInput`]: ErrorKind::InvalidInput
316 #[stable(feature = "io_invalid_data", since = "1.2.0")]
317 InvalidData,
318 /// The I/O operation's timeout expired, causing it to be canceled.
319 #[stable(feature = "rust1", since = "1.0.0")]
320 TimedOut,
321 /// An error returned when an operation could not be completed because a
322 /// call to [`write`] returned [`Ok(0)`].
323 ///
324 /// This typically means that an operation could only succeed if it wrote a
325 /// particular number of bytes but only a smaller number of bytes could be
326 /// written.
327 ///
328 /// [`write`]: crate::io::Write::write
329 /// [`Ok(0)`]: Ok
330 #[stable(feature = "rust1", since = "1.0.0")]
331 WriteZero,
332 /// The underlying storage (typically, a filesystem) is full.
333 ///
334 /// This does not include out of quota errors.
335 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
336 StorageFull,
337 /// Seek on unseekable file.
338 ///
339 /// Seeking was attempted on an open file handle which is not suitable for seeking - for
340 /// example, on Unix, a named pipe opened with `File::open`.
341 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
342 NotSeekable,
343 /// Filesystem quota or some other kind of quota was exceeded.
344 #[stable(feature = "io_error_quota_exceeded", since = "1.85.0")]
345 QuotaExceeded,
346 /// File larger than allowed or supported.
347 ///
348 /// This might arise from a hard limit of the underlying filesystem or file access API, or from
349 /// an administratively imposed resource limitation. Simple disk full, and out of quota, have
350 /// their own errors.
351 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
352 FileTooLarge,
353 /// Resource is busy.
354 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
355 ResourceBusy,
356 /// Executable file is busy.
357 ///
358 /// An attempt was made to write to a file which is also in use as a running program. (Not all
359 /// operating systems detect this situation.)
360 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
361 ExecutableFileBusy,
362 /// Deadlock (avoided).
363 ///
364 /// A file locking operation would result in deadlock. This situation is typically detected, if
365 /// at all, on a best-effort basis.
366 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
367 Deadlock,
368 /// Cross-device or cross-filesystem (hard) link or rename.
369 #[stable(feature = "io_error_crosses_devices", since = "1.85.0")]
370 CrossesDevices,
371 /// Too many (hard) links to the same filesystem object.
372 ///
373 /// The filesystem does not support making so many hardlinks to the same file.
374 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
375 TooManyLinks,
376 /// A filename was invalid.
377 ///
378 /// This error can also occur if a length limit for a name was exceeded.
379 #[stable(feature = "io_error_invalid_filename", since = "1.87.0")]
380 InvalidFilename,
381 /// Program argument list too long.
382 ///
383 /// When trying to run an external program, a system or process limit on the size of the
384 /// arguments would have been exceeded.
385 #[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
386 ArgumentListTooLong,
387 /// This operation was interrupted.
388 ///
389 /// Interrupted operations can typically be retried.
390 #[stable(feature = "rust1", since = "1.0.0")]
391 Interrupted,
392
393 /// This operation is unsupported on this platform.
394 ///
395 /// This means that the operation can never succeed.
396 #[stable(feature = "unsupported_error", since = "1.53.0")]
397 Unsupported,
398
399 // ErrorKinds which are primarily categorisations for OS error
400 // codes should be added above.
401 //
402 /// An error returned when an operation could not be completed because an
403 /// "end of file" was reached prematurely.
404 ///
405 /// This typically means that an operation could only succeed if it read a
406 /// particular number of bytes but only a smaller number of bytes could be
407 /// read.
408 #[stable(feature = "read_exact", since = "1.6.0")]
409 UnexpectedEof,
410
411 /// An operation could not be completed, because it failed
412 /// to allocate enough memory.
413 #[stable(feature = "out_of_memory_error", since = "1.54.0")]
414 OutOfMemory,
415
416 /// The operation was partially successful and needs to be checked
417 /// later on due to not blocking.
418 #[unstable(feature = "io_error_inprogress", issue = "130840")]
419 InProgress,
420
421 // "Unusual" error kinds which do not correspond simply to (sets
422 // of) OS error codes, should be added just above this comment.
423 // `Other` and `Uncategorized` should remain at the end:
424 //
425 /// A custom error that does not fall under any other I/O error kind.
426 ///
427 /// This can be used to construct your own [`Error`]s that do not match any
428 /// [`ErrorKind`].
429 ///
430 /// This [`ErrorKind`] is not used by the standard library.
431 ///
432 /// Errors from the standard library that do not fall under any of the I/O
433 /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
434 /// New [`ErrorKind`]s might be added in the future for some of those.
435 #[stable(feature = "rust1", since = "1.0.0")]
436 Other,
437
438 /// Any I/O error from the standard library that's not part of this list.
439 ///
440 /// Errors that are `Uncategorized` now may move to a different or a new
441 /// [`ErrorKind`] variant in the future. It is not recommended to match
442 /// an error against `Uncategorized`; use a wildcard match (`_`) instead.
443 #[unstable(feature = "io_error_uncategorized", issue = "none")]
444 #[doc(hidden)]
445 Uncategorized,
446}
447
448impl ErrorKind {
449 pub(crate) fn as_str(&self) -> &'static str {
450 use ErrorKind::*;
451 match *self {
452 // tidy-alphabetical-start
453 AddrInUse => "address in use",
454 AddrNotAvailable => "address not available",
455 AlreadyExists => "entity already exists",
456 ArgumentListTooLong => "argument list too long",
457 BrokenPipe => "broken pipe",
458 ConnectionAborted => "connection aborted",
459 ConnectionRefused => "connection refused",
460 ConnectionReset => "connection reset",
461 CrossesDevices => "cross-device link or rename",
462 Deadlock => "deadlock",
463 DirectoryNotEmpty => "directory not empty",
464 ExecutableFileBusy => "executable file busy",
465 FileTooLarge => "file too large",
466 FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
467 HostUnreachable => "host unreachable",
468 InProgress => "in progress",
469 Interrupted => "operation interrupted",
470 InvalidData => "invalid data",
471 InvalidFilename => "invalid filename",
472 InvalidInput => "invalid input parameter",
473 IsADirectory => "is a directory",
474 NetworkDown => "network down",
475 NetworkUnreachable => "network unreachable",
476 NotADirectory => "not a directory",
477 NotConnected => "not connected",
478 NotFound => "entity not found",
479 NotSeekable => "seek on unseekable file",
480 Other => "other error",
481 OutOfMemory => "out of memory",
482 PermissionDenied => "permission denied",
483 QuotaExceeded => "quota exceeded",
484 ReadOnlyFilesystem => "read-only filesystem or storage medium",
485 ResourceBusy => "resource busy",
486 StaleNetworkFileHandle => "stale network file handle",
487 StorageFull => "no storage space",
488 TimedOut => "timed out",
489 TooManyLinks => "too many links",
490 Uncategorized => "uncategorized error",
491 UnexpectedEof => "unexpected end of file",
492 Unsupported => "unsupported",
493 WouldBlock => "operation would block",
494 WriteZero => "write zero",
495 // tidy-alphabetical-end
496 }
497 }
498}
499
500#[stable(feature = "io_errorkind_display", since = "1.60.0")]
501impl fmt::Display for ErrorKind {
502 /// Shows a human-readable description of the `ErrorKind`.
503 ///
504 /// This is similar to `impl Display for Error`, but doesn't require first converting to Error.
505 ///
506 /// # Examples
507 /// ```
508 /// use std::io::ErrorKind;
509 /// assert_eq!("entity not found", ErrorKind::NotFound.to_string());
510 /// ```
511 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
512 fmt.write_str(self.as_str())
513 }
514}
515
516/// Intended for use for errors not exposed to the user, where allocating onto
517/// the heap (for normal construction via Error::new) is too costly.
518#[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
519impl From<ErrorKind> for Error {
520 /// Converts an [`ErrorKind`] into an [`Error`].
521 ///
522 /// This conversion creates a new error with a simple representation of error kind.
523 ///
524 /// # Examples
525 ///
526 /// ```
527 /// use std::io::{Error, ErrorKind};
528 ///
529 /// let not_found = ErrorKind::NotFound;
530 /// let error = Error::from(not_found);
531 /// assert_eq!("entity not found", format!("{error}"));
532 /// ```
533 #[inline]
534 fn from(kind: ErrorKind) -> Error {
535 Error { repr: Repr::new_simple(kind) }
536 }
537}
538
539impl Error {
540 /// Creates a new I/O error from a known kind of error as well as an
541 /// arbitrary error payload.
542 ///
543 /// This function is used to generically create I/O errors which do not
544 /// originate from the OS itself. The `error` argument is an arbitrary
545 /// payload which will be contained in this [`Error`].
546 ///
547 /// Note that this function allocates memory on the heap.
548 /// If no extra payload is required, use the `From` conversion from
549 /// `ErrorKind`.
550 ///
551 /// # Examples
552 ///
553 /// ```
554 /// use std::io::{Error, ErrorKind};
555 ///
556 /// // errors can be created from strings
557 /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
558 ///
559 /// // errors can also be created from other errors
560 /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
561 ///
562 /// // creating an error without payload (and without memory allocation)
563 /// let eof_error = Error::from(ErrorKind::UnexpectedEof);
564 /// ```
565 #[stable(feature = "rust1", since = "1.0.0")]
566 #[cfg_attr(not(test), rustc_diagnostic_item = "io_error_new")]
567 #[inline(never)]
568 pub fn new<E>(kind: ErrorKind, error: E) -> Error
569 where
570 E: Into<Box<dyn error::Error + Send + Sync>>,
571 {
572 Self::_new(kind, error.into())
573 }
574
575 /// Creates a new I/O error from an arbitrary error payload.
576 ///
577 /// This function is used to generically create I/O errors which do not
578 /// originate from the OS itself. It is a shortcut for [`Error::new`]
579 /// with [`ErrorKind::Other`].
580 ///
581 /// # Examples
582 ///
583 /// ```
584 /// use std::io::Error;
585 ///
586 /// // errors can be created from strings
587 /// let custom_error = Error::other("oh no!");
588 ///
589 /// // errors can also be created from other errors
590 /// let custom_error2 = Error::other(custom_error);
591 /// ```
592 #[stable(feature = "io_error_other", since = "1.74.0")]
593 pub fn other<E>(error: E) -> Error
594 where
595 E: Into<Box<dyn error::Error + Send + Sync>>,
596 {
597 Self::_new(ErrorKind::Other, error.into())
598 }
599
600 fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
601 Error { repr: Repr::new_custom(Box::new(Custom { kind, error })) }
602 }
603
604 /// Creates a new I/O error from a known kind of error as well as a constant
605 /// message.
606 ///
607 /// This function does not allocate.
608 ///
609 /// You should not use this directly, and instead use the `const_error!`
610 /// macro: `io::const_error!(ErrorKind::Something, "some_message")`.
611 ///
612 /// This function should maybe change to `from_static_message<const MSG: &'static
613 /// str>(kind: ErrorKind)` in the future, when const generics allow that.
614 #[inline]
615 #[doc(hidden)]
616 #[unstable(feature = "io_const_error_internals", issue = "none")]
617 pub const fn from_static_message(msg: &'static SimpleMessage) -> Error {
618 Self { repr: Repr::new_simple_message(msg) }
619 }
620
621 /// Returns an error representing the last OS error which occurred.
622 ///
623 /// This function reads the value of `errno` for the target platform (e.g.
624 /// `GetLastError` on Windows) and will return a corresponding instance of
625 /// [`Error`] for the error code.
626 ///
627 /// This should be called immediately after a call to a platform function,
628 /// otherwise the state of the error value is indeterminate. In particular,
629 /// other standard library functions may call platform functions that may
630 /// (or may not) reset the error value even if they succeed.
631 ///
632 /// # Examples
633 ///
634 /// ```
635 /// use std::io::Error;
636 ///
637 /// let os_error = Error::last_os_error();
638 /// println!("last OS error: {os_error:?}");
639 /// ```
640 #[stable(feature = "rust1", since = "1.0.0")]
641 #[doc(alias = "GetLastError")]
642 #[doc(alias = "errno")]
643 #[must_use]
644 #[inline]
645 pub fn last_os_error() -> Error {
646 Error::from_raw_os_error(sys::os::errno())
647 }
648
649 /// Creates a new instance of an [`Error`] from a particular OS error code.
650 ///
651 /// # Examples
652 ///
653 /// On Linux:
654 ///
655 /// ```
656 /// # if cfg!(target_os = "linux") {
657 /// use std::io;
658 ///
659 /// let error = io::Error::from_raw_os_error(22);
660 /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
661 /// # }
662 /// ```
663 ///
664 /// On Windows:
665 ///
666 /// ```
667 /// # if cfg!(windows) {
668 /// use std::io;
669 ///
670 /// let error = io::Error::from_raw_os_error(10022);
671 /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
672 /// # }
673 /// ```
674 #[stable(feature = "rust1", since = "1.0.0")]
675 #[must_use]
676 #[inline]
677 pub fn from_raw_os_error(code: RawOsError) -> Error {
678 Error { repr: Repr::new_os(code) }
679 }
680
681 /// Returns the OS error that this error represents (if any).
682 ///
683 /// If this [`Error`] was constructed via [`last_os_error`] or
684 /// [`from_raw_os_error`], then this function will return [`Some`], otherwise
685 /// it will return [`None`].
686 ///
687 /// [`last_os_error`]: Error::last_os_error
688 /// [`from_raw_os_error`]: Error::from_raw_os_error
689 ///
690 /// # Examples
691 ///
692 /// ```
693 /// use std::io::{Error, ErrorKind};
694 ///
695 /// fn print_os_error(err: &Error) {
696 /// if let Some(raw_os_err) = err.raw_os_error() {
697 /// println!("raw OS error: {raw_os_err:?}");
698 /// } else {
699 /// println!("Not an OS error");
700 /// }
701 /// }
702 ///
703 /// fn main() {
704 /// // Will print "raw OS error: ...".
705 /// print_os_error(&Error::last_os_error());
706 /// // Will print "Not an OS error".
707 /// print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
708 /// }
709 /// ```
710 #[stable(feature = "rust1", since = "1.0.0")]
711 #[must_use]
712 #[inline]
713 pub fn raw_os_error(&self) -> Option<RawOsError> {
714 match self.repr.data() {
715 ErrorData::Os(i) => Some(i),
716 ErrorData::Custom(..) => None,
717 ErrorData::Simple(..) => None,
718 ErrorData::SimpleMessage(..) => None,
719 }
720 }
721
722 /// Returns a reference to the inner error wrapped by this error (if any).
723 ///
724 /// If this [`Error`] was constructed via [`new`] then this function will
725 /// return [`Some`], otherwise it will return [`None`].
726 ///
727 /// [`new`]: Error::new
728 ///
729 /// # Examples
730 ///
731 /// ```
732 /// use std::io::{Error, ErrorKind};
733 ///
734 /// fn print_error(err: &Error) {
735 /// if let Some(inner_err) = err.get_ref() {
736 /// println!("Inner error: {inner_err:?}");
737 /// } else {
738 /// println!("No inner error");
739 /// }
740 /// }
741 ///
742 /// fn main() {
743 /// // Will print "No inner error".
744 /// print_error(&Error::last_os_error());
745 /// // Will print "Inner error: ...".
746 /// print_error(&Error::new(ErrorKind::Other, "oh no!"));
747 /// }
748 /// ```
749 #[stable(feature = "io_error_inner", since = "1.3.0")]
750 #[must_use]
751 #[inline]
752 pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
753 match self.repr.data() {
754 ErrorData::Os(..) => None,
755 ErrorData::Simple(..) => None,
756 ErrorData::SimpleMessage(..) => None,
757 ErrorData::Custom(c) => Some(&*c.error),
758 }
759 }
760
761 /// Returns a mutable reference to the inner error wrapped by this error
762 /// (if any).
763 ///
764 /// If this [`Error`] was constructed via [`new`] then this function will
765 /// return [`Some`], otherwise it will return [`None`].
766 ///
767 /// [`new`]: Error::new
768 ///
769 /// # Examples
770 ///
771 /// ```
772 /// use std::io::{Error, ErrorKind};
773 /// use std::{error, fmt};
774 /// use std::fmt::Display;
775 ///
776 /// #[derive(Debug)]
777 /// struct MyError {
778 /// v: String,
779 /// }
780 ///
781 /// impl MyError {
782 /// fn new() -> MyError {
783 /// MyError {
784 /// v: "oh no!".to_string()
785 /// }
786 /// }
787 ///
788 /// fn change_message(&mut self, new_message: &str) {
789 /// self.v = new_message.to_string();
790 /// }
791 /// }
792 ///
793 /// impl error::Error for MyError {}
794 ///
795 /// impl Display for MyError {
796 /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797 /// write!(f, "MyError: {}", self.v)
798 /// }
799 /// }
800 ///
801 /// fn change_error(mut err: Error) -> Error {
802 /// if let Some(inner_err) = err.get_mut() {
803 /// inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!");
804 /// }
805 /// err
806 /// }
807 ///
808 /// fn print_error(err: &Error) {
809 /// if let Some(inner_err) = err.get_ref() {
810 /// println!("Inner error: {inner_err}");
811 /// } else {
812 /// println!("No inner error");
813 /// }
814 /// }
815 ///
816 /// fn main() {
817 /// // Will print "No inner error".
818 /// print_error(&change_error(Error::last_os_error()));
819 /// // Will print "Inner error: ...".
820 /// print_error(&change_error(Error::new(ErrorKind::Other, MyError::new())));
821 /// }
822 /// ```
823 #[stable(feature = "io_error_inner", since = "1.3.0")]
824 #[must_use]
825 #[inline]
826 pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
827 match self.repr.data_mut() {
828 ErrorData::Os(..) => None,
829 ErrorData::Simple(..) => None,
830 ErrorData::SimpleMessage(..) => None,
831 ErrorData::Custom(c) => Some(&mut *c.error),
832 }
833 }
834
835 /// Consumes the `Error`, returning its inner error (if any).
836 ///
837 /// If this [`Error`] was constructed via [`new`] or [`other`],
838 /// then this function will return [`Some`],
839 /// otherwise it will return [`None`].
840 ///
841 /// [`new`]: Error::new
842 /// [`other`]: Error::other
843 ///
844 /// # Examples
845 ///
846 /// ```
847 /// use std::io::{Error, ErrorKind};
848 ///
849 /// fn print_error(err: Error) {
850 /// if let Some(inner_err) = err.into_inner() {
851 /// println!("Inner error: {inner_err}");
852 /// } else {
853 /// println!("No inner error");
854 /// }
855 /// }
856 ///
857 /// fn main() {
858 /// // Will print "No inner error".
859 /// print_error(Error::last_os_error());
860 /// // Will print "Inner error: ...".
861 /// print_error(Error::new(ErrorKind::Other, "oh no!"));
862 /// }
863 /// ```
864 #[stable(feature = "io_error_inner", since = "1.3.0")]
865 #[must_use = "`self` will be dropped if the result is not used"]
866 #[inline]
867 pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
868 match self.repr.into_data() {
869 ErrorData::Os(..) => None,
870 ErrorData::Simple(..) => None,
871 ErrorData::SimpleMessage(..) => None,
872 ErrorData::Custom(c) => Some(c.error),
873 }
874 }
875
876 /// Attempts to downcast the custom boxed error to `E`.
877 ///
878 /// If this [`Error`] contains a custom boxed error,
879 /// then it would attempt downcasting on the boxed error,
880 /// otherwise it will return [`Err`].
881 ///
882 /// If the custom boxed error has the same type as `E`, it will return [`Ok`],
883 /// otherwise it will also return [`Err`].
884 ///
885 /// This method is meant to be a convenience routine for calling
886 /// `Box<dyn Error + Sync + Send>::downcast` on the custom boxed error, returned by
887 /// [`Error::into_inner`].
888 ///
889 ///
890 /// # Examples
891 ///
892 /// ```
893 /// use std::fmt;
894 /// use std::io;
895 /// use std::error::Error;
896 ///
897 /// #[derive(Debug)]
898 /// enum E {
899 /// Io(io::Error),
900 /// SomeOtherVariant,
901 /// }
902 ///
903 /// impl fmt::Display for E {
904 /// // ...
905 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
906 /// # todo!()
907 /// # }
908 /// }
909 /// impl Error for E {}
910 ///
911 /// impl From<io::Error> for E {
912 /// fn from(err: io::Error) -> E {
913 /// err.downcast::<E>()
914 /// .unwrap_or_else(E::Io)
915 /// }
916 /// }
917 ///
918 /// impl From<E> for io::Error {
919 /// fn from(err: E) -> io::Error {
920 /// match err {
921 /// E::Io(io_error) => io_error,
922 /// e => io::Error::new(io::ErrorKind::Other, e),
923 /// }
924 /// }
925 /// }
926 ///
927 /// # fn main() {
928 /// let e = E::SomeOtherVariant;
929 /// // Convert it to an io::Error
930 /// let io_error = io::Error::from(e);
931 /// // Cast it back to the original variant
932 /// let e = E::from(io_error);
933 /// assert!(matches!(e, E::SomeOtherVariant));
934 ///
935 /// let io_error = io::Error::from(io::ErrorKind::AlreadyExists);
936 /// // Convert it to E
937 /// let e = E::from(io_error);
938 /// // Cast it back to the original variant
939 /// let io_error = io::Error::from(e);
940 /// assert_eq!(io_error.kind(), io::ErrorKind::AlreadyExists);
941 /// assert!(io_error.get_ref().is_none());
942 /// assert!(io_error.raw_os_error().is_none());
943 /// # }
944 /// ```
945 #[stable(feature = "io_error_downcast", since = "1.79.0")]
946 pub fn downcast<E>(self) -> result::Result<E, Self>
947 where
948 E: error::Error + Send + Sync + 'static,
949 {
950 match self.repr.into_data() {
951 ErrorData::Custom(b) if b.error.is::<E>() => {
952 let res = (*b).error.downcast::<E>();
953
954 // downcast is a really trivial and is marked as inline, so
955 // it's likely be inlined here.
956 //
957 // And the compiler should be able to eliminate the branch
958 // that produces `Err` here since b.error.is::<E>()
959 // returns true.
960 Ok(*res.unwrap())
961 }
962 repr_data => Err(Self { repr: Repr::new(repr_data) }),
963 }
964 }
965
966 /// Returns the corresponding [`ErrorKind`] for this error.
967 ///
968 /// This may be a value set by Rust code constructing custom `io::Error`s,
969 /// or if this `io::Error` was sourced from the operating system,
970 /// it will be a value inferred from the system's error encoding.
971 /// See [`last_os_error`] for more details.
972 ///
973 /// [`last_os_error`]: Error::last_os_error
974 ///
975 /// # Examples
976 ///
977 /// ```
978 /// use std::io::{Error, ErrorKind};
979 ///
980 /// fn print_error(err: Error) {
981 /// println!("{:?}", err.kind());
982 /// }
983 ///
984 /// fn main() {
985 /// // As no error has (visibly) occurred, this may print anything!
986 /// // It likely prints a placeholder for unidentified (non-)errors.
987 /// print_error(Error::last_os_error());
988 /// // Will print "AddrInUse".
989 /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
990 /// }
991 /// ```
992 #[stable(feature = "rust1", since = "1.0.0")]
993 #[must_use]
994 #[inline]
995 pub fn kind(&self) -> ErrorKind {
996 match self.repr.data() {
997 ErrorData::Os(code) => sys::decode_error_kind(code),
998 ErrorData::Custom(c) => c.kind,
999 ErrorData::Simple(kind) => kind,
1000 ErrorData::SimpleMessage(m) => m.kind,
1001 }
1002 }
1003
1004 #[inline]
1005 pub(crate) fn is_interrupted(&self) -> bool {
1006 match self.repr.data() {
1007 ErrorData::Os(code) => sys::is_interrupted(code),
1008 ErrorData::Custom(c) => c.kind == ErrorKind::Interrupted,
1009 ErrorData::Simple(kind) => kind == ErrorKind::Interrupted,
1010 ErrorData::SimpleMessage(m) => m.kind == ErrorKind::Interrupted,
1011 }
1012 }
1013}
1014
1015impl fmt::Debug for Repr {
1016 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1017 match self.data() {
1018 ErrorData::Os(code) => fmt
1019 .debug_struct("Os")
1020 .field("code", &code)
1021 .field("kind", &sys::decode_error_kind(code))
1022 .field("message", &sys::os::error_string(code))
1023 .finish(),
1024 ErrorData::Custom(c) => fmt::Debug::fmt(&c, fmt),
1025 ErrorData::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
1026 ErrorData::SimpleMessage(msg) => fmt
1027 .debug_struct("Error")
1028 .field("kind", &msg.kind)
1029 .field("message", &msg.message)
1030 .finish(),
1031 }
1032 }
1033}
1034
1035#[stable(feature = "rust1", since = "1.0.0")]
1036impl fmt::Display for Error {
1037 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1038 match self.repr.data() {
1039 ErrorData::Os(code) => {
1040 let detail = sys::os::error_string(code);
1041 write!(fmt, "{detail} (os error {code})")
1042 }
1043 ErrorData::Custom(ref c) => c.error.fmt(fmt),
1044 ErrorData::Simple(kind) => write!(fmt, "{}", kind.as_str()),
1045 ErrorData::SimpleMessage(msg) => msg.message.fmt(fmt),
1046 }
1047 }
1048}
1049
1050#[stable(feature = "rust1", since = "1.0.0")]
1051impl error::Error for Error {
1052 #[allow(deprecated, deprecated_in_future)]
1053 fn description(&self) -> &str {
1054 match self.repr.data() {
1055 ErrorData::Os(..) | ErrorData::Simple(..) => self.kind().as_str(),
1056 ErrorData::SimpleMessage(msg) => msg.message,
1057 ErrorData::Custom(c) => c.error.description(),
1058 }
1059 }
1060
1061 #[allow(deprecated)]
1062 fn cause(&self) -> Option<&dyn error::Error> {
1063 match self.repr.data() {
1064 ErrorData::Os(..) => None,
1065 ErrorData::Simple(..) => None,
1066 ErrorData::SimpleMessage(..) => None,
1067 ErrorData::Custom(c) => c.error.cause(),
1068 }
1069 }
1070
1071 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
1072 match self.repr.data() {
1073 ErrorData::Os(..) => None,
1074 ErrorData::Simple(..) => None,
1075 ErrorData::SimpleMessage(..) => None,
1076 ErrorData::Custom(c) => c.error.source(),
1077 }
1078 }
1079}
1080
1081fn _assert_error_is_sync_send() {
1082 fn _is_sync_send<T: Sync + Send>() {}
1083 _is_sync_send::<Error>();
1084}