alloc/io/error.rs
1use core::io::Custom;
2#[cfg_attr(no_global_oom_handling, expect(unused_imports))]
3use core::io::CustomOwner;
4use core::{error, result};
5
6use crate::boxed::Box;
7#[cfg_attr(any(no_rc, no_sync, no_global_oom_handling), expect(unused_imports))]
8use crate::io::const_error;
9use crate::io::{Error, ErrorKind};
10
11impl Error {
12 /// Creates a new I/O error from a known kind of error as well as an
13 /// arbitrary error payload.
14 ///
15 /// This function is used to generically create I/O errors which do not
16 /// originate from the OS itself. The `error` argument is an arbitrary
17 /// payload which will be contained in this [`Error`].
18 ///
19 /// Note that this function allocates memory on the heap.
20 /// If no extra payload is required, use the `From` conversion from
21 /// `ErrorKind`.
22 ///
23 /// # Examples
24 ///
25 /// ```
26 /// use std::io::{Error, ErrorKind};
27 ///
28 /// // errors can be created from strings
29 /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
30 ///
31 /// // errors can also be created from other errors
32 /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
33 ///
34 /// // creating an error without payload (and without memory allocation)
35 /// let eof_error = Error::from(ErrorKind::UnexpectedEof);
36 /// ```
37 #[cfg(not(no_global_oom_handling))]
38 #[stable(feature = "rust1", since = "1.0.0")]
39 #[cfg_attr(not(test), rustc_diagnostic_item = "io_error_new")]
40 #[inline(never)]
41 #[rustc_allow_incoherent_impl]
42 pub fn new<E>(kind: ErrorKind, error: E) -> Error
43 where
44 E: Into<Box<dyn error::Error + Send + Sync>>,
45 {
46 let custom = custom_owner_from_box(kind, error.into());
47
48 // SAFETY: `custom_owner` has been constructed from a `Box` from the `alloc` crate.
49 unsafe { Self::from_custom_owner(custom) }
50 }
51
52 /// Creates a new I/O error from an arbitrary error payload.
53 ///
54 /// This function is used to generically create I/O errors which do not
55 /// originate from the OS itself. It is a shortcut for [`Error::new`][new]
56 /// with [`ErrorKind::Other`].
57 ///
58 /// [new]: struct.Error.html#method.new
59 ///
60 /// # Examples
61 ///
62 /// ```
63 /// use std::io::Error;
64 ///
65 /// // errors can be created from strings
66 /// let custom_error = Error::other("oh no!");
67 ///
68 /// // errors can also be created from other errors
69 /// let custom_error2 = Error::other(custom_error);
70 /// ```
71 #[cfg(not(no_global_oom_handling))]
72 #[stable(feature = "io_error_other", since = "1.74.0")]
73 #[rustc_allow_incoherent_impl]
74 pub fn other<E>(error: E) -> Error
75 where
76 E: Into<Box<dyn error::Error + Send + Sync>>,
77 {
78 Self::new(ErrorKind::Other, error)
79 }
80
81 /// Consumes the `Error`, returning its inner error (if any).
82 ///
83 /// If this [`Error`] was constructed via [`new`][new] or [`other`][other],
84 /// then this function will return [`Some`],
85 /// otherwise it will return [`None`].
86 ///
87 /// [new]: struct.Error.html#method.new
88 /// [other]: struct.Error.html#method.other
89 ///
90 /// # Examples
91 ///
92 /// ```
93 /// use std::io::{Error, ErrorKind};
94 ///
95 /// fn print_error(err: Error) {
96 /// if let Some(inner_err) = err.into_inner() {
97 /// println!("Inner error: {inner_err}");
98 /// } else {
99 /// println!("No inner error");
100 /// }
101 /// }
102 ///
103 /// fn main() {
104 /// // Will print "No inner error".
105 /// print_error(Error::last_os_error());
106 /// // Will print "Inner error: ...".
107 /// print_error(Error::new(ErrorKind::Other, "oh no!"));
108 /// }
109 /// ```
110 #[stable(feature = "io_error_inner", since = "1.3.0")]
111 #[must_use = "`self` will be dropped if the result is not used"]
112 #[inline]
113 #[rustc_allow_incoherent_impl]
114 pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
115 let custom_owner = self.into_custom_owner().ok()?;
116
117 let ptr = custom_owner.into_raw().as_ptr();
118
119 // SAFETY:
120 // `Error` can only contain a `CustomOwner` if it was constructed using `Box::into_raw`.
121 let custom = unsafe { Box::<Custom>::from_raw(ptr) };
122
123 let ptr = custom.into_raw().as_ptr();
124
125 // SAFETY:
126 // Any `CustomOwner` from an `Error` was constructed by the `alloc` crate
127 // to contain a `Custom` which itself was constructed with `Box::into_raw`.
128 Some(unsafe { Box::from_raw(ptr) })
129 }
130
131 /// Attempts to downcast the custom boxed error to `E`.
132 ///
133 /// If this [`Error`] contains a custom boxed error,
134 /// then it would attempt downcasting on the boxed error,
135 /// otherwise it will return [`Err`].
136 ///
137 /// If the custom boxed error has the same type as `E`, it will return [`Ok`],
138 /// otherwise it will also return [`Err`].
139 ///
140 /// This method is meant to be a convenience routine for calling
141 /// `Box<dyn Error + Sync + Send>::downcast` on the custom boxed error, returned by
142 /// [`Error::into_inner`][into_inner].
143 ///
144 /// [into_inner]: struct.Error.html#method.into_inner
145 ///
146 /// # Examples
147 ///
148 /// ```
149 /// use std::fmt;
150 /// use std::io;
151 /// use std::error::Error;
152 ///
153 /// #[derive(Debug)]
154 /// enum E {
155 /// Io(io::Error),
156 /// SomeOtherVariant,
157 /// }
158 ///
159 /// impl fmt::Display for E {
160 /// // ...
161 /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 /// # todo!()
163 /// # }
164 /// }
165 /// impl Error for E {}
166 ///
167 /// impl From<io::Error> for E {
168 /// fn from(err: io::Error) -> E {
169 /// err.downcast::<E>()
170 /// .unwrap_or_else(E::Io)
171 /// }
172 /// }
173 ///
174 /// impl From<E> for io::Error {
175 /// fn from(err: E) -> io::Error {
176 /// match err {
177 /// E::Io(io_error) => io_error,
178 /// e => io::Error::new(io::ErrorKind::Other, e),
179 /// }
180 /// }
181 /// }
182 ///
183 /// # fn main() {
184 /// let e = E::SomeOtherVariant;
185 /// // Convert it to an io::Error
186 /// let io_error = io::Error::from(e);
187 /// // Cast it back to the original variant
188 /// let e = E::from(io_error);
189 /// assert!(matches!(e, E::SomeOtherVariant));
190 ///
191 /// let io_error = io::Error::from(io::ErrorKind::AlreadyExists);
192 /// // Convert it to E
193 /// let e = E::from(io_error);
194 /// // Cast it back to the original variant
195 /// let io_error = io::Error::from(e);
196 /// assert_eq!(io_error.kind(), io::ErrorKind::AlreadyExists);
197 /// assert!(io_error.get_ref().is_none());
198 /// assert!(io_error.raw_os_error().is_none());
199 /// # }
200 /// ```
201 #[stable(feature = "io_error_downcast", since = "1.79.0")]
202 #[rustc_allow_incoherent_impl]
203 pub fn downcast<E>(self) -> result::Result<E, Self>
204 where
205 E: error::Error + Send + Sync + 'static,
206 {
207 if let Some(e) = self.get_ref()
208 && e.is::<E>()
209 {
210 if let Some(b) = self.into_inner()
211 && let Ok(err) = b.downcast::<E>()
212 {
213 Ok(*err)
214 } else {
215 // Safety: We have just checked that the condition is true
216 unsafe { core::hint::unreachable_unchecked() }
217 }
218 } else {
219 Err(self)
220 }
221 }
222}
223
224#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
225#[stable(feature = "rust1", since = "1.0.0")]
226impl From<crate::ffi::NulError> for Error {
227 /// Converts a [`crate::ffi::NulError`] into a [`Error`].
228 fn from(_: crate::ffi::NulError) -> Error {
229 const_error!(ErrorKind::InvalidInput, "data provided contains a nul byte")
230 }
231}
232
233#[stable(feature = "io_error_from_try_reserve", since = "1.78.0")]
234impl From<crate::collections::TryReserveError> for Error {
235 /// Converts `TryReserveError` to an error with [`ErrorKind::OutOfMemory`].
236 ///
237 /// `TryReserveError` won't be available as the error `source()`,
238 /// but this may change in the future.
239 fn from(_: crate::collections::TryReserveError) -> Error {
240 // ErrorData::Custom allocates, which isn't great for handling OOM errors.
241 ErrorKind::OutOfMemory.into()
242 }
243}
244
245#[cfg(not(no_global_oom_handling))]
246fn custom_owner_from_box(
247 kind: ErrorKind,
248 error: Box<dyn core::error::Error + Send + Sync>,
249) -> CustomOwner {
250 /// # Safety
251 ///
252 /// `ptr` must be valid to pass into `Box::from_raw`.
253 unsafe fn drop_box_raw<T: ?Sized>(ptr: *mut T) {
254 // SAFETY
255 // Caller ensures `ptr` is valid to pass into `Box::from_raw`.
256 drop(unsafe { Box::from_raw(ptr) })
257 }
258
259 // SAFETY: the pointer returned by Box::into_raw is non-null.
260 let error = unsafe { core::ptr::NonNull::new_unchecked(Box::into_raw(error)) };
261
262 // SAFETY:
263 // * `error` is valid up to a static lifetime, and owns its pointee.
264 // * `drop_box_raw` is safe to call for the pointer `error` exactly once.
265 // * `drop_box_raw` is safe to call on a pointer to this instance of `Custom`,
266 // and will be stored in a `CustomOwner`.
267 let custom = unsafe { Custom::from_raw(kind, error, drop_box_raw, drop_box_raw) };
268
269 // SAFETY: the pointer returned by Box::into_raw is non-null.
270 let custom = unsafe { core::ptr::NonNull::new_unchecked(Box::into_raw(Box::new(custom))) };
271
272 // SAFETY: the `outer_drop` provided to `custom` is valid for itself.
273 unsafe { CustomOwner::from_raw(custom) }
274}