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