]> git.lizzy.rs Git - rust.git/blob - library/std/src/io/error.rs
Rollup merge of #92300 - Itus-Shield:mips64-openwrt, r=nagisa
[rust.git] / library / std / src / io / error.rs
1 #[cfg(test)]
2 mod tests;
3
4 use crate::convert::From;
5 use crate::error;
6 use crate::fmt;
7 use crate::result;
8 use crate::sys;
9
10 /// A specialized [`Result`] type for I/O operations.
11 ///
12 /// This type is broadly used across [`std::io`] for any operation which may
13 /// produce an error.
14 ///
15 /// This typedef is generally used to avoid writing out [`io::Error`] directly and
16 /// is otherwise a direct mapping to [`Result`].
17 ///
18 /// While usual Rust style is to import types directly, aliases of [`Result`]
19 /// often are not, to make it easier to distinguish between them. [`Result`] is
20 /// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
21 /// will generally use `io::Result` instead of shadowing the [prelude]'s import
22 /// of [`std::result::Result`][`Result`].
23 ///
24 /// [`std::io`]: crate::io
25 /// [`io::Error`]: Error
26 /// [`Result`]: crate::result::Result
27 /// [prelude]: crate::prelude
28 ///
29 /// # Examples
30 ///
31 /// A convenience function that bubbles an `io::Result` to its caller:
32 ///
33 /// ```
34 /// use std::io;
35 ///
36 /// fn get_string() -> io::Result<String> {
37 ///     let mut buffer = String::new();
38 ///
39 ///     io::stdin().read_line(&mut buffer)?;
40 ///
41 ///     Ok(buffer)
42 /// }
43 /// ```
44 #[stable(feature = "rust1", since = "1.0.0")]
45 pub type Result<T> = result::Result<T, Error>;
46
47 /// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
48 /// associated traits.
49 ///
50 /// Errors mostly originate from the underlying OS, but custom instances of
51 /// `Error` can be created with crafted error messages and a particular value of
52 /// [`ErrorKind`].
53 ///
54 /// [`Read`]: crate::io::Read
55 /// [`Write`]: crate::io::Write
56 /// [`Seek`]: crate::io::Seek
57 #[stable(feature = "rust1", since = "1.0.0")]
58 pub struct Error {
59     repr: Repr,
60 }
61
62 #[stable(feature = "rust1", since = "1.0.0")]
63 impl fmt::Debug for Error {
64     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65         fmt::Debug::fmt(&self.repr, f)
66     }
67 }
68
69 enum Repr {
70     Os(i32),
71     Simple(ErrorKind),
72     // &str is a fat pointer, but &&str is a thin pointer.
73     SimpleMessage(ErrorKind, &'static &'static str),
74     Custom(Box<Custom>),
75 }
76
77 #[derive(Debug)]
78 struct Custom {
79     kind: ErrorKind,
80     error: Box<dyn error::Error + Send + Sync>,
81 }
82
83 /// A list specifying general categories of I/O error.
84 ///
85 /// This list is intended to grow over time and it is not recommended to
86 /// exhaustively match against it.
87 ///
88 /// It is used with the [`io::Error`] type.
89 ///
90 /// [`io::Error`]: Error
91 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
92 #[stable(feature = "rust1", since = "1.0.0")]
93 #[allow(deprecated)]
94 #[non_exhaustive]
95 pub enum ErrorKind {
96     /// An entity was not found, often a file.
97     #[stable(feature = "rust1", since = "1.0.0")]
98     NotFound,
99     /// The operation lacked the necessary privileges to complete.
100     #[stable(feature = "rust1", since = "1.0.0")]
101     PermissionDenied,
102     /// The connection was refused by the remote server.
103     #[stable(feature = "rust1", since = "1.0.0")]
104     ConnectionRefused,
105     /// The connection was reset by the remote server.
106     #[stable(feature = "rust1", since = "1.0.0")]
107     ConnectionReset,
108     /// The remote host is not reachable.
109     #[unstable(feature = "io_error_more", issue = "86442")]
110     HostUnreachable,
111     /// The network containing the remote host is not reachable.
112     #[unstable(feature = "io_error_more", issue = "86442")]
113     NetworkUnreachable,
114     /// The connection was aborted (terminated) by the remote server.
115     #[stable(feature = "rust1", since = "1.0.0")]
116     ConnectionAborted,
117     /// The network operation failed because it was not connected yet.
118     #[stable(feature = "rust1", since = "1.0.0")]
119     NotConnected,
120     /// A socket address could not be bound because the address is already in
121     /// use elsewhere.
122     #[stable(feature = "rust1", since = "1.0.0")]
123     AddrInUse,
124     /// A nonexistent interface was requested or the requested address was not
125     /// local.
126     #[stable(feature = "rust1", since = "1.0.0")]
127     AddrNotAvailable,
128     /// The system's networking is down.
129     #[unstable(feature = "io_error_more", issue = "86442")]
130     NetworkDown,
131     /// The operation failed because a pipe was closed.
132     #[stable(feature = "rust1", since = "1.0.0")]
133     BrokenPipe,
134     /// An entity already exists, often a file.
135     #[stable(feature = "rust1", since = "1.0.0")]
136     AlreadyExists,
137     /// The operation needs to block to complete, but the blocking operation was
138     /// requested to not occur.
139     #[stable(feature = "rust1", since = "1.0.0")]
140     WouldBlock,
141     /// A filesystem object is, unexpectedly, not a directory.
142     ///
143     /// For example, a filesystem path was specified where one of the intermediate directory
144     /// components was, in fact, a plain file.
145     #[unstable(feature = "io_error_more", issue = "86442")]
146     NotADirectory,
147     /// The filesystem object is, unexpectedly, a directory.
148     ///
149     /// A directory was specified when a non-directory was expected.
150     #[unstable(feature = "io_error_more", issue = "86442")]
151     IsADirectory,
152     /// A non-empty directory was specified where an empty directory was expected.
153     #[unstable(feature = "io_error_more", issue = "86442")]
154     DirectoryNotEmpty,
155     /// The filesystem or storage medium is read-only, but a write operation was attempted.
156     #[unstable(feature = "io_error_more", issue = "86442")]
157     ReadOnlyFilesystem,
158     /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
159     ///
160     /// There was a loop (or excessively long chain) resolving a filesystem object
161     /// or file IO object.
162     ///
163     /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the
164     /// system-specific limit on the depth of symlink traversal.
165     #[unstable(feature = "io_error_more", issue = "86442")]
166     FilesystemLoop,
167     /// Stale network file handle.
168     ///
169     /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
170     /// by problems with the network or server.
171     #[unstable(feature = "io_error_more", issue = "86442")]
172     StaleNetworkFileHandle,
173     /// A parameter was incorrect.
174     #[stable(feature = "rust1", since = "1.0.0")]
175     InvalidInput,
176     /// Data not valid for the operation were encountered.
177     ///
178     /// Unlike [`InvalidInput`], this typically means that the operation
179     /// parameters were valid, however the error was caused by malformed
180     /// input data.
181     ///
182     /// For example, a function that reads a file into a string will error with
183     /// `InvalidData` if the file's contents are not valid UTF-8.
184     ///
185     /// [`InvalidInput`]: ErrorKind::InvalidInput
186     #[stable(feature = "io_invalid_data", since = "1.2.0")]
187     InvalidData,
188     /// The I/O operation's timeout expired, causing it to be canceled.
189     #[stable(feature = "rust1", since = "1.0.0")]
190     TimedOut,
191     /// An error returned when an operation could not be completed because a
192     /// call to [`write`] returned [`Ok(0)`].
193     ///
194     /// This typically means that an operation could only succeed if it wrote a
195     /// particular number of bytes but only a smaller number of bytes could be
196     /// written.
197     ///
198     /// [`write`]: crate::io::Write::write
199     /// [`Ok(0)`]: Ok
200     #[stable(feature = "rust1", since = "1.0.0")]
201     WriteZero,
202     /// The underlying storage (typically, a filesystem) is full.
203     ///
204     /// This does not include out of quota errors.
205     #[unstable(feature = "io_error_more", issue = "86442")]
206     StorageFull,
207     /// Seek on unseekable file.
208     ///
209     /// Seeking was attempted on an open file handle which is not suitable for seeking - for
210     /// example, on Unix, a named pipe opened with `File::open`.
211     #[unstable(feature = "io_error_more", issue = "86442")]
212     NotSeekable,
213     /// Filesystem quota was exceeded.
214     #[unstable(feature = "io_error_more", issue = "86442")]
215     FilesystemQuotaExceeded,
216     /// File larger than allowed or supported.
217     ///
218     /// This might arise from a hard limit of the underlying filesystem or file access API, or from
219     /// an administratively imposed resource limitation.  Simple disk full, and out of quota, have
220     /// their own errors.
221     #[unstable(feature = "io_error_more", issue = "86442")]
222     FileTooLarge,
223     /// Resource is busy.
224     #[unstable(feature = "io_error_more", issue = "86442")]
225     ResourceBusy,
226     /// Executable file is busy.
227     ///
228     /// An attempt was made to write to a file which is also in use as a running program.  (Not all
229     /// operating systems detect this situation.)
230     #[unstable(feature = "io_error_more", issue = "86442")]
231     ExecutableFileBusy,
232     /// Deadlock (avoided).
233     ///
234     /// A file locking operation would result in deadlock.  This situation is typically detected, if
235     /// at all, on a best-effort basis.
236     #[unstable(feature = "io_error_more", issue = "86442")]
237     Deadlock,
238     /// Cross-device or cross-filesystem (hard) link or rename.
239     #[unstable(feature = "io_error_more", issue = "86442")]
240     CrossesDevices,
241     /// Too many (hard) links to the same filesystem object.
242     ///
243     /// The filesystem does not support making so many hardlinks to the same file.
244     #[unstable(feature = "io_error_more", issue = "86442")]
245     TooManyLinks,
246     /// Filename too long.
247     ///
248     /// The limit might be from the underlying filesystem or API, or an administratively imposed
249     /// resource limit.
250     #[unstable(feature = "io_error_more", issue = "86442")]
251     FilenameTooLong,
252     /// Program argument list too long.
253     ///
254     /// When trying to run an external program, a system or process limit on the size of the
255     /// arguments would have been exceeded.
256     #[unstable(feature = "io_error_more", issue = "86442")]
257     ArgumentListTooLong,
258     /// This operation was interrupted.
259     ///
260     /// Interrupted operations can typically be retried.
261     #[stable(feature = "rust1", since = "1.0.0")]
262     Interrupted,
263
264     /// This operation is unsupported on this platform.
265     ///
266     /// This means that the operation can never succeed.
267     #[stable(feature = "unsupported_error", since = "1.53.0")]
268     Unsupported,
269
270     // ErrorKinds which are primarily categorisations for OS error
271     // codes should be added above.
272     //
273     /// An error returned when an operation could not be completed because an
274     /// "end of file" was reached prematurely.
275     ///
276     /// This typically means that an operation could only succeed if it read a
277     /// particular number of bytes but only a smaller number of bytes could be
278     /// read.
279     #[stable(feature = "read_exact", since = "1.6.0")]
280     UnexpectedEof,
281
282     /// An operation could not be completed, because it failed
283     /// to allocate enough memory.
284     #[stable(feature = "out_of_memory_error", since = "1.54.0")]
285     OutOfMemory,
286
287     // "Unusual" error kinds which do not correspond simply to (sets
288     // of) OS error codes, should be added just above this comment.
289     // `Other` and `Uncategorised` should remain at the end:
290     //
291     /// A custom error that does not fall under any other I/O error kind.
292     ///
293     /// This can be used to construct your own [`Error`]s that do not match any
294     /// [`ErrorKind`].
295     ///
296     /// This [`ErrorKind`] is not used by the standard library.
297     ///
298     /// Errors from the standard library that do not fall under any of the I/O
299     /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
300     /// New [`ErrorKind`]s might be added in the future for some of those.
301     #[stable(feature = "rust1", since = "1.0.0")]
302     Other,
303
304     /// Any I/O error from the standard library that's not part of this list.
305     ///
306     /// Errors that are `Uncategorized` now may move to a different or a new
307     /// [`ErrorKind`] variant in the future. It is not recommended to match
308     /// an error against `Uncategorized`; use a wildcard match (`_`) instead.
309     #[unstable(feature = "io_error_uncategorized", issue = "none")]
310     #[doc(hidden)]
311     Uncategorized,
312 }
313
314 impl ErrorKind {
315     pub(crate) fn as_str(&self) -> &'static str {
316         use ErrorKind::*;
317         // Strictly alphabetical, please.  (Sadly rustfmt cannot do this yet.)
318         match *self {
319             AddrInUse => "address in use",
320             AddrNotAvailable => "address not available",
321             AlreadyExists => "entity already exists",
322             ArgumentListTooLong => "argument list too long",
323             BrokenPipe => "broken pipe",
324             ConnectionAborted => "connection aborted",
325             ConnectionRefused => "connection refused",
326             ConnectionReset => "connection reset",
327             CrossesDevices => "cross-device link or rename",
328             Deadlock => "deadlock",
329             DirectoryNotEmpty => "directory not empty",
330             ExecutableFileBusy => "executable file busy",
331             FileTooLarge => "file too large",
332             FilenameTooLong => "filename too long",
333             FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
334             FilesystemQuotaExceeded => "filesystem quota exceeded",
335             HostUnreachable => "host unreachable",
336             Interrupted => "operation interrupted",
337             InvalidData => "invalid data",
338             InvalidInput => "invalid input parameter",
339             IsADirectory => "is a directory",
340             NetworkDown => "network down",
341             NetworkUnreachable => "network unreachable",
342             NotADirectory => "not a directory",
343             NotConnected => "not connected",
344             NotFound => "entity not found",
345             NotSeekable => "seek on unseekable file",
346             Other => "other error",
347             OutOfMemory => "out of memory",
348             PermissionDenied => "permission denied",
349             ReadOnlyFilesystem => "read-only filesystem or storage medium",
350             ResourceBusy => "resource busy",
351             StaleNetworkFileHandle => "stale network file handle",
352             StorageFull => "no storage space",
353             TimedOut => "timed out",
354             TooManyLinks => "too many links",
355             Uncategorized => "uncategorized error",
356             UnexpectedEof => "unexpected end of file",
357             Unsupported => "unsupported",
358             WouldBlock => "operation would block",
359             WriteZero => "write zero",
360         }
361     }
362 }
363
364 #[stable(feature = "io_errorkind_display", since = "1.60.0")]
365 impl fmt::Display for ErrorKind {
366     /// Shows a human-readable description of the `ErrorKind`.
367     ///
368     /// This is similar to `impl Display for Error`, but doesn't require first converting to Error.
369     ///
370     /// # Examples
371     /// ```
372     /// use std::io::ErrorKind;
373     /// assert_eq!("entity not found", ErrorKind::NotFound.to_string());
374     /// ```
375     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
376         fmt.write_str(self.as_str())
377     }
378 }
379
380 /// Intended for use for errors not exposed to the user, where allocating onto
381 /// the heap (for normal construction via Error::new) is too costly.
382 #[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
383 impl From<ErrorKind> for Error {
384     /// Converts an [`ErrorKind`] into an [`Error`].
385     ///
386     /// This conversion creates a new error with a simple representation of error kind.
387     ///
388     /// # Examples
389     ///
390     /// ```
391     /// use std::io::{Error, ErrorKind};
392     ///
393     /// let not_found = ErrorKind::NotFound;
394     /// let error = Error::from(not_found);
395     /// assert_eq!("entity not found", format!("{}", error));
396     /// ```
397     #[inline]
398     fn from(kind: ErrorKind) -> Error {
399         Error { repr: Repr::Simple(kind) }
400     }
401 }
402
403 impl Error {
404     /// Creates a new I/O error from a known kind of error as well as an
405     /// arbitrary error payload.
406     ///
407     /// This function is used to generically create I/O errors which do not
408     /// originate from the OS itself. The `error` argument is an arbitrary
409     /// payload which will be contained in this [`Error`].
410     ///
411     /// If no extra payload is required, use the `From` conversion from
412     /// `ErrorKind`.
413     ///
414     /// # Examples
415     ///
416     /// ```
417     /// use std::io::{Error, ErrorKind};
418     ///
419     /// // errors can be created from strings
420     /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
421     ///
422     /// // errors can also be created from other errors
423     /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
424     ///
425     /// // creating an error without payload
426     /// let eof_error = Error::from(ErrorKind::UnexpectedEof);
427     /// ```
428     #[stable(feature = "rust1", since = "1.0.0")]
429     pub fn new<E>(kind: ErrorKind, error: E) -> Error
430     where
431         E: Into<Box<dyn error::Error + Send + Sync>>,
432     {
433         Self::_new(kind, error.into())
434     }
435
436     /// Creates a new I/O error from an arbitrary error payload.
437     ///
438     /// This function is used to generically create I/O errors which do not
439     /// originate from the OS itself. It is a shortcut for [`Error::new`]
440     /// with [`ErrorKind::Other`].
441     ///
442     /// # Examples
443     ///
444     /// ```
445     /// #![feature(io_error_other)]
446     ///
447     /// use std::io::Error;
448     ///
449     /// // errors can be created from strings
450     /// let custom_error = Error::other("oh no!");
451     ///
452     /// // errors can also be created from other errors
453     /// let custom_error2 = Error::other(custom_error);
454     /// ```
455     #[unstable(feature = "io_error_other", issue = "91946")]
456     pub fn other<E>(error: E) -> Error
457     where
458         E: Into<Box<dyn error::Error + Send + Sync>>,
459     {
460         Self::_new(ErrorKind::Other, error.into())
461     }
462
463     fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
464         Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
465     }
466
467     /// Creates a new I/O error from a known kind of error as well as a
468     /// constant message.
469     ///
470     /// This function does not allocate.
471     ///
472     /// This function should maybe change to
473     /// `new_const<const MSG: &'static str>(kind: ErrorKind)`
474     /// in the future, when const generics allow that.
475     #[inline]
476     pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error {
477         Self { repr: Repr::SimpleMessage(kind, message) }
478     }
479
480     /// Returns an error representing the last OS error which occurred.
481     ///
482     /// This function reads the value of `errno` for the target platform (e.g.
483     /// `GetLastError` on Windows) and will return a corresponding instance of
484     /// [`Error`] for the error code.
485     ///
486     /// This should be called immediately after a call to a platform function,
487     /// otherwise the state of the error value is indeterminate. In particular,
488     /// other standard library functions may call platform functions that may
489     /// (or may not) reset the error value even if they succeed.
490     ///
491     /// # Examples
492     ///
493     /// ```
494     /// use std::io::Error;
495     ///
496     /// let os_error = Error::last_os_error();
497     /// println!("last OS error: {:?}", os_error);
498     /// ```
499     #[stable(feature = "rust1", since = "1.0.0")]
500     #[must_use]
501     #[inline]
502     pub fn last_os_error() -> Error {
503         Error::from_raw_os_error(sys::os::errno() as i32)
504     }
505
506     /// Creates a new instance of an [`Error`] from a particular OS error code.
507     ///
508     /// # Examples
509     ///
510     /// On Linux:
511     ///
512     /// ```
513     /// # if cfg!(target_os = "linux") {
514     /// use std::io;
515     ///
516     /// let error = io::Error::from_raw_os_error(22);
517     /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
518     /// # }
519     /// ```
520     ///
521     /// On Windows:
522     ///
523     /// ```
524     /// # if cfg!(windows) {
525     /// use std::io;
526     ///
527     /// let error = io::Error::from_raw_os_error(10022);
528     /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
529     /// # }
530     /// ```
531     #[stable(feature = "rust1", since = "1.0.0")]
532     #[must_use]
533     #[inline]
534     pub fn from_raw_os_error(code: i32) -> Error {
535         Error { repr: Repr::Os(code) }
536     }
537
538     /// Returns the OS error that this error represents (if any).
539     ///
540     /// If this [`Error`] was constructed via [`last_os_error`] or
541     /// [`from_raw_os_error`], then this function will return [`Some`], otherwise
542     /// it will return [`None`].
543     ///
544     /// [`last_os_error`]: Error::last_os_error
545     /// [`from_raw_os_error`]: Error::from_raw_os_error
546     ///
547     /// # Examples
548     ///
549     /// ```
550     /// use std::io::{Error, ErrorKind};
551     ///
552     /// fn print_os_error(err: &Error) {
553     ///     if let Some(raw_os_err) = err.raw_os_error() {
554     ///         println!("raw OS error: {:?}", raw_os_err);
555     ///     } else {
556     ///         println!("Not an OS error");
557     ///     }
558     /// }
559     ///
560     /// fn main() {
561     ///     // Will print "raw OS error: ...".
562     ///     print_os_error(&Error::last_os_error());
563     ///     // Will print "Not an OS error".
564     ///     print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
565     /// }
566     /// ```
567     #[stable(feature = "rust1", since = "1.0.0")]
568     #[must_use]
569     #[inline]
570     pub fn raw_os_error(&self) -> Option<i32> {
571         match self.repr {
572             Repr::Os(i) => Some(i),
573             Repr::Custom(..) => None,
574             Repr::Simple(..) => None,
575             Repr::SimpleMessage(..) => None,
576         }
577     }
578
579     /// Returns a reference to the inner error wrapped by this error (if any).
580     ///
581     /// If this [`Error`] was constructed via [`new`] then this function will
582     /// return [`Some`], otherwise it will return [`None`].
583     ///
584     /// [`new`]: Error::new
585     ///
586     /// # Examples
587     ///
588     /// ```
589     /// use std::io::{Error, ErrorKind};
590     ///
591     /// fn print_error(err: &Error) {
592     ///     if let Some(inner_err) = err.get_ref() {
593     ///         println!("Inner error: {:?}", inner_err);
594     ///     } else {
595     ///         println!("No inner error");
596     ///     }
597     /// }
598     ///
599     /// fn main() {
600     ///     // Will print "No inner error".
601     ///     print_error(&Error::last_os_error());
602     ///     // Will print "Inner error: ...".
603     ///     print_error(&Error::new(ErrorKind::Other, "oh no!"));
604     /// }
605     /// ```
606     #[stable(feature = "io_error_inner", since = "1.3.0")]
607     #[must_use]
608     #[inline]
609     pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
610         match self.repr {
611             Repr::Os(..) => None,
612             Repr::Simple(..) => None,
613             Repr::SimpleMessage(..) => None,
614             Repr::Custom(ref c) => Some(&*c.error),
615         }
616     }
617
618     /// Returns a mutable reference to the inner error wrapped by this error
619     /// (if any).
620     ///
621     /// If this [`Error`] was constructed via [`new`] then this function will
622     /// return [`Some`], otherwise it will return [`None`].
623     ///
624     /// [`new`]: Error::new
625     ///
626     /// # Examples
627     ///
628     /// ```
629     /// use std::io::{Error, ErrorKind};
630     /// use std::{error, fmt};
631     /// use std::fmt::Display;
632     ///
633     /// #[derive(Debug)]
634     /// struct MyError {
635     ///     v: String,
636     /// }
637     ///
638     /// impl MyError {
639     ///     fn new() -> MyError {
640     ///         MyError {
641     ///             v: "oh no!".to_string()
642     ///         }
643     ///     }
644     ///
645     ///     fn change_message(&mut self, new_message: &str) {
646     ///         self.v = new_message.to_string();
647     ///     }
648     /// }
649     ///
650     /// impl error::Error for MyError {}
651     ///
652     /// impl Display for MyError {
653     ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
654     ///         write!(f, "MyError: {}", &self.v)
655     ///     }
656     /// }
657     ///
658     /// fn change_error(mut err: Error) -> Error {
659     ///     if let Some(inner_err) = err.get_mut() {
660     ///         inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!");
661     ///     }
662     ///     err
663     /// }
664     ///
665     /// fn print_error(err: &Error) {
666     ///     if let Some(inner_err) = err.get_ref() {
667     ///         println!("Inner error: {}", inner_err);
668     ///     } else {
669     ///         println!("No inner error");
670     ///     }
671     /// }
672     ///
673     /// fn main() {
674     ///     // Will print "No inner error".
675     ///     print_error(&change_error(Error::last_os_error()));
676     ///     // Will print "Inner error: ...".
677     ///     print_error(&change_error(Error::new(ErrorKind::Other, MyError::new())));
678     /// }
679     /// ```
680     #[stable(feature = "io_error_inner", since = "1.3.0")]
681     #[must_use]
682     #[inline]
683     pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
684         match self.repr {
685             Repr::Os(..) => None,
686             Repr::Simple(..) => None,
687             Repr::SimpleMessage(..) => None,
688             Repr::Custom(ref mut c) => Some(&mut *c.error),
689         }
690     }
691
692     /// Consumes the `Error`, returning its inner error (if any).
693     ///
694     /// If this [`Error`] was constructed via [`new`] then this function will
695     /// return [`Some`], otherwise it will return [`None`].
696     ///
697     /// [`new`]: Error::new
698     ///
699     /// # Examples
700     ///
701     /// ```
702     /// use std::io::{Error, ErrorKind};
703     ///
704     /// fn print_error(err: Error) {
705     ///     if let Some(inner_err) = err.into_inner() {
706     ///         println!("Inner error: {}", inner_err);
707     ///     } else {
708     ///         println!("No inner error");
709     ///     }
710     /// }
711     ///
712     /// fn main() {
713     ///     // Will print "No inner error".
714     ///     print_error(Error::last_os_error());
715     ///     // Will print "Inner error: ...".
716     ///     print_error(Error::new(ErrorKind::Other, "oh no!"));
717     /// }
718     /// ```
719     #[stable(feature = "io_error_inner", since = "1.3.0")]
720     #[must_use = "`self` will be dropped if the result is not used"]
721     #[inline]
722     pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
723         match self.repr {
724             Repr::Os(..) => None,
725             Repr::Simple(..) => None,
726             Repr::SimpleMessage(..) => None,
727             Repr::Custom(c) => Some(c.error),
728         }
729     }
730
731     /// Returns the corresponding [`ErrorKind`] for this error.
732     ///
733     /// # Examples
734     ///
735     /// ```
736     /// use std::io::{Error, ErrorKind};
737     ///
738     /// fn print_error(err: Error) {
739     ///     println!("{:?}", err.kind());
740     /// }
741     ///
742     /// fn main() {
743     ///     // Will print "Uncategorized".
744     ///     print_error(Error::last_os_error());
745     ///     // Will print "AddrInUse".
746     ///     print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
747     /// }
748     /// ```
749     #[stable(feature = "rust1", since = "1.0.0")]
750     #[must_use]
751     #[inline]
752     pub fn kind(&self) -> ErrorKind {
753         match self.repr {
754             Repr::Os(code) => sys::decode_error_kind(code),
755             Repr::Custom(ref c) => c.kind,
756             Repr::Simple(kind) => kind,
757             Repr::SimpleMessage(kind, _) => kind,
758         }
759     }
760 }
761
762 impl fmt::Debug for Repr {
763     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
764         match *self {
765             Repr::Os(code) => fmt
766                 .debug_struct("Os")
767                 .field("code", &code)
768                 .field("kind", &sys::decode_error_kind(code))
769                 .field("message", &sys::os::error_string(code))
770                 .finish(),
771             Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
772             Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
773             Repr::SimpleMessage(kind, &message) => {
774                 fmt.debug_struct("Error").field("kind", &kind).field("message", &message).finish()
775             }
776         }
777     }
778 }
779
780 #[stable(feature = "rust1", since = "1.0.0")]
781 impl fmt::Display for Error {
782     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
783         match self.repr {
784             Repr::Os(code) => {
785                 let detail = sys::os::error_string(code);
786                 write!(fmt, "{} (os error {})", detail, code)
787             }
788             Repr::Custom(ref c) => c.error.fmt(fmt),
789             Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
790             Repr::SimpleMessage(_, &msg) => msg.fmt(fmt),
791         }
792     }
793 }
794
795 #[stable(feature = "rust1", since = "1.0.0")]
796 impl error::Error for Error {
797     #[allow(deprecated, deprecated_in_future)]
798     fn description(&self) -> &str {
799         match self.repr {
800             Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(),
801             Repr::SimpleMessage(_, &msg) => msg,
802             Repr::Custom(ref c) => c.error.description(),
803         }
804     }
805
806     #[allow(deprecated)]
807     fn cause(&self) -> Option<&dyn error::Error> {
808         match self.repr {
809             Repr::Os(..) => None,
810             Repr::Simple(..) => None,
811             Repr::SimpleMessage(..) => None,
812             Repr::Custom(ref c) => c.error.cause(),
813         }
814     }
815
816     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
817         match self.repr {
818             Repr::Os(..) => None,
819             Repr::Simple(..) => None,
820             Repr::SimpleMessage(..) => None,
821             Repr::Custom(ref c) => c.error.source(),
822         }
823     }
824 }
825
826 fn _assert_error_is_sync_send() {
827     fn _is_sync_send<T: Sync + Send>() {}
828     _is_sync_send::<Error>();
829 }