Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 657453d

Browse files
committedOct 13, 2023
move std::io::Error to core
1 parent 130ff8c commit 657453d

File tree

19 files changed

+2084
-576
lines changed

19 files changed

+2084
-576
lines changed
 

‎library/alloc/src/io/error.rs

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#[cfg(test)]
2+
mod tests;
3+
4+
use crate::{alloc::Global, boxed::Box, string::String};
5+
use core::io::{
6+
const_io_error,
7+
error_internals::{AllocVTable, Custom, ErrorBox, ErrorString},
8+
Error, ErrorKind,
9+
};
10+
use core::{alloc::Allocator, error, ptr, result};
11+
12+
unsafe fn set_alloc_vtable() {
13+
static ALLOC_VTABLE: AllocVTable =
14+
AllocVTable { deallocate: |ptr, layout| unsafe { Global.deallocate(ptr, layout) } };
15+
unsafe {
16+
ALLOC_VTABLE.install();
17+
}
18+
}
19+
20+
fn into_error_box<T: ?Sized>(value: Box<T>) -> ErrorBox<T> {
21+
unsafe {
22+
set_alloc_vtable();
23+
ErrorBox::from_raw(Box::into_raw(value))
24+
}
25+
}
26+
27+
fn into_box<T: ?Sized>(v: ErrorBox<T>) -> Box<T> {
28+
unsafe { Box::from_raw(v.into_raw()) }
29+
}
30+
31+
impl From<String> for ErrorString {
32+
fn from(value: String) -> Self {
33+
unsafe {
34+
set_alloc_vtable();
35+
let (buf, length, capacity) = value.into_raw_parts();
36+
ErrorString::from_raw_parts(
37+
ErrorBox::from_raw(ptr::slice_from_raw_parts_mut(buf.cast(), capacity)).into(),
38+
length,
39+
)
40+
}
41+
}
42+
}
43+
44+
#[stable(feature = "rust1", since = "1.0.0")]
45+
impl From<crate::ffi::NulError> for Error {
46+
/// Converts a [`crate::ffi::NulError`] into a [`Error`].
47+
fn from(_: crate::ffi::NulError) -> Error {
48+
const_io_error!(ErrorKind::InvalidInput, "data provided contains a nul byte")
49+
}
50+
}
51+
52+
impl Error {
53+
/// Creates a new I/O error from a known kind of error as well as an
54+
/// arbitrary error payload.
55+
///
56+
/// This function is used to generically create I/O errors which do not
57+
/// originate from the OS itself. The `error` argument is an arbitrary
58+
/// payload which will be contained in this [`Error`].
59+
///
60+
/// Note that this function allocates memory on the heap.
61+
/// If no extra payload is required, use the `From` conversion from
62+
/// `ErrorKind`.
63+
///
64+
/// # Examples
65+
///
66+
/// ```
67+
/// use std::io::{Error, ErrorKind};
68+
///
69+
/// // errors can be created from strings
70+
/// let custom_error = Error::new(ErrorKind::Other, "oh no!");
71+
///
72+
/// // errors can also be created from other errors
73+
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
74+
///
75+
/// // creating an error without payload (and without memory allocation)
76+
/// let eof_error = Error::from(ErrorKind::UnexpectedEof);
77+
/// ```
78+
#[stable(feature = "rust1", since = "1.0.0")]
79+
#[rustc_allow_incoherent_impl]
80+
pub fn new<E>(kind: ErrorKind, error: E) -> Error
81+
where
82+
E: Into<Box<dyn error::Error + Send + Sync>>,
83+
{
84+
Self::_new(kind, error.into())
85+
}
86+
87+
/// Creates a new I/O error from an arbitrary error payload.
88+
///
89+
/// This function is used to generically create I/O errors which do not
90+
/// originate from the OS itself. It is a shortcut for [`Error::new`]
91+
/// with [`ErrorKind::Other`].
92+
///
93+
/// # Examples
94+
///
95+
/// ```
96+
/// #![feature(io_error_other)]
97+
///
98+
/// use std::io::Error;
99+
///
100+
/// // errors can be created from strings
101+
/// let custom_error = Error::other("oh no!");
102+
///
103+
/// // errors can also be created from other errors
104+
/// let custom_error2 = Error::other(custom_error);
105+
/// ```
106+
#[unstable(feature = "io_error_other", issue = "91946")]
107+
#[rustc_allow_incoherent_impl]
108+
pub fn other<E>(error: E) -> Error
109+
where
110+
E: Into<Box<dyn error::Error + Send + Sync>>,
111+
{
112+
Self::_new(ErrorKind::Other, error.into())
113+
}
114+
115+
#[rustc_allow_incoherent_impl]
116+
fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
117+
Error::_new_custom(into_error_box(Box::new(Custom { kind, error: into_error_box(error) })))
118+
}
119+
120+
/// Consumes the `Error`, returning its inner error (if any).
121+
///
122+
/// If this [`Error`] was constructed via [`new`] then this function will
123+
/// return [`Some`], otherwise it will return [`None`].
124+
///
125+
/// [`new`]: Error::new
126+
///
127+
/// # Examples
128+
///
129+
/// ```
130+
/// use std::io::{Error, ErrorKind};
131+
///
132+
/// fn print_error(err: Error) {
133+
/// if let Some(inner_err) = err.into_inner() {
134+
/// println!("Inner error: {inner_err}");
135+
/// } else {
136+
/// println!("No inner error");
137+
/// }
138+
/// }
139+
///
140+
/// fn main() {
141+
/// // Will print "No inner error".
142+
/// print_error(Error::last_os_error());
143+
/// // Will print "Inner error: ...".
144+
/// print_error(Error::new(ErrorKind::Other, "oh no!"));
145+
/// }
146+
/// ```
147+
#[stable(feature = "io_error_inner", since = "1.3.0")]
148+
#[must_use = "`self` will be dropped if the result is not used"]
149+
#[inline]
150+
#[rustc_allow_incoherent_impl]
151+
pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
152+
self.into_inner_impl().map(into_box)
153+
}
154+
155+
/// Attempt to downgrade the inner error to `E` if any.
156+
///
157+
/// If this [`Error`] was constructed via [`new`] then this function will
158+
/// attempt to perform downgrade on it, otherwise it will return [`Err`].
159+
///
160+
/// If downgrade succeeds, it will return [`Ok`], otherwise it will also
161+
/// return [`Err`].
162+
///
163+
/// [`new`]: Error::new
164+
///
165+
/// # Examples
166+
///
167+
/// ```
168+
/// #![feature(io_error_downcast)]
169+
///
170+
/// use std::fmt;
171+
/// use std::io;
172+
/// use std::error::Error;
173+
///
174+
/// #[derive(Debug)]
175+
/// enum E {
176+
/// Io(io::Error),
177+
/// SomeOtherVariant,
178+
/// }
179+
///
180+
/// impl fmt::Display for E {
181+
/// // ...
182+
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183+
/// # todo!()
184+
/// # }
185+
/// }
186+
/// impl Error for E {}
187+
///
188+
/// impl From<io::Error> for E {
189+
/// fn from(err: io::Error) -> E {
190+
/// err.downcast::<E>()
191+
/// .map(|b| *b)
192+
/// .unwrap_or_else(E::Io)
193+
/// }
194+
/// }
195+
/// ```
196+
#[unstable(feature = "io_error_downcast", issue = "99262")]
197+
#[rustc_allow_incoherent_impl]
198+
pub fn downcast<E>(self) -> result::Result<Box<E>, Self>
199+
where
200+
E: error::Error + Send + Sync + 'static,
201+
{
202+
self.downcast_impl::<E>().map(|p| unsafe { Box::from_raw(p) })
203+
}
204+
}

‎library/alloc/src/io/error/tests.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use core::error;
2+
use core::fmt;
3+
use core::io::{Error, ErrorKind};
4+
5+
#[test]
6+
fn test_downcasting() {
7+
#[derive(Debug)]
8+
struct TestError;
9+
10+
impl fmt::Display for TestError {
11+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12+
f.write_str("asdf")
13+
}
14+
}
15+
16+
impl error::Error for TestError {}
17+
18+
// we have to call all of these UFCS style right now since method
19+
// resolution won't implicitly drop the Send+Sync bounds
20+
let mut err = Error::new(ErrorKind::Other, TestError);
21+
assert!(err.get_ref().unwrap().is::<TestError>());
22+
assert_eq!("asdf", err.get_ref().unwrap().to_string());
23+
assert!(err.get_mut().unwrap().is::<TestError>());
24+
let extracted = err.into_inner().unwrap();
25+
extracted.downcast::<TestError>().unwrap();
26+
}

‎library/alloc/src/io/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//! Traits, helpers, and type definitions for core I/O functionality.
2+
3+
#![unstable(feature = "alloc_io", issue = "none")]
4+
5+
pub use core::io::*;
6+
7+
#[cfg(target_has_atomic_load_store = "ptr")]
8+
mod error;

‎library/alloc/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@
121121
#![feature(const_size_of_val)]
122122
#![feature(const_waker)]
123123
#![feature(core_intrinsics)]
124+
#![feature(core_io)]
125+
#![feature(core_io_error_internals)]
124126
#![feature(core_panic)]
125127
#![feature(deprecated_suggestion)]
126128
#![feature(dispatch_from_dyn)]
@@ -177,6 +179,7 @@
177179
#![feature(associated_type_bounds)]
178180
#![feature(c_unwind)]
179181
#![feature(cfg_sanitize)]
182+
#![feature(cfg_target_has_atomic)]
180183
#![feature(const_mut_refs)]
181184
#![feature(const_precise_live_drops)]
182185
#![feature(const_ptr_write)]
@@ -246,6 +249,7 @@ pub mod collections;
246249
#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
247250
pub mod ffi;
248251
pub mod fmt;
252+
pub mod io;
249253
#[cfg(not(no_rc))]
250254
pub mod rc;
251255
pub mod slice;
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.