Skip to content

Commit dcd5688

Browse files
committed
Move io::Error to alloc
1 parent 9bead2b commit dcd5688

15 files changed

Lines changed: 300 additions & 199 deletions

File tree

Lines changed: 110 additions & 136 deletions
Large diffs are not rendered by default.

library/std/src/io/error/repr_bitpacked.rs renamed to library/alloc/src/io/error/repr_bitpacked.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ use core::num::NonZeroUsize;
107107
use core::ptr::NonNull;
108108

109109
use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
110+
use crate::boxed::Box;
110111

111112
// The 2 least-significant bits are used as tag.
112113
const TAG_MASK: usize = 0b11;

library/std/src/io/error/repr_unpacked.rs renamed to library/alloc/src/io/error/repr_unpacked.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! would have no benefit.
44
55
use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
6+
use crate::boxed::Box;
67

78
type Inner = ErrorData<Box<Custom>>;
89

library/alloc/src/io/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! Traits, helpers, and type definitions for core I/O functionality.
2+
3+
#[unstable(feature = "read_buf", issue = "78485")]
4+
pub use core::io::{BorrowedBuf, BorrowedCursor};
5+
6+
#[doc(hidden)]
7+
#[unstable(feature = "io_const_error_internals", issue = "none")]
8+
pub use self::error::SimpleMessage;
9+
#[unstable(feature = "io_const_error", issue = "133448")]
10+
pub use self::error::const_error;
11+
#[stable(feature = "rust1", since = "1.0.0")]
12+
pub use self::error::{Error, ErrorKind, Result};
13+
#[unstable(feature = "io_error_internals", issue = "none")]
14+
#[doc(hidden)]
15+
pub use self::error::{RawOsError, os::OsFunctions};
16+
17+
mod error;

library/alloc/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@
6363
#![doc(
6464
html_playground_url = "https://play.rust-lang.org/",
6565
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
66-
test(no_crate_inject, attr(allow(unused_variables, duplicate_features), deny(warnings)))
66+
test(
67+
no_crate_inject,
68+
attr(allow(unused_variables, duplicate_features, dead_code), deny(warnings))
69+
)
6770
)]
6871
#![doc(auto_cfg(hide(no_global_oom_handling, no_rc, no_sync, target_has_atomic = "ptr")))]
6972
#![doc(rust_logo)]
@@ -86,6 +89,7 @@
8689
//
8790
// Library features:
8891
// tidy-alphabetical-start
92+
#![cfg_attr(not(no_global_oom_handling), feature(io_const_error))]
8993
#![feature(allocator_api)]
9094
#![feature(array_into_iter_constructors)]
9195
#![feature(ascii_char)]
@@ -224,6 +228,9 @@ pub mod collections;
224228
pub mod ffi;
225229
pub mod fmt;
226230
pub mod intrinsics;
231+
#[unstable(feature = "alloc_io", issue = "154046")]
232+
#[cfg(not(no_global_oom_handling))]
233+
pub mod io;
227234
#[cfg(not(no_rc))]
228235
pub mod rc;
229236
pub mod slice;

library/std/src/io/error/mod.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//! OS-dependent public methods of `Error`
2+
3+
#[cfg(test)]
4+
mod tests;
5+
6+
#[cfg(not(test))]
7+
use alloc::io::{Error, RawOsError};
8+
9+
// FIXME: for some reason, enabling these in `test` config makes them defined twice,
10+
// but it does not seem to be the case with other incoherent items.
11+
#[cfg(not(test))]
12+
impl Error {
13+
/// Creates a new instance of an [`Error`] from a particular OS error code.
14+
///
15+
/// # Examples
16+
///
17+
/// On Linux:
18+
///
19+
/// ```
20+
/// # if cfg!(target_os = "linux") {
21+
/// use std::io;
22+
///
23+
/// let error = io::Error::from_raw_os_error(22);
24+
/// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
25+
/// # }
26+
/// ```
27+
///
28+
/// On Windows:
29+
///
30+
/// ```
31+
/// # if cfg!(windows) {
32+
/// use std::io;
33+
///
34+
/// let error = io::Error::from_raw_os_error(10022);
35+
/// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
36+
/// # }
37+
/// ```
38+
#[stable(feature = "rust1", since = "1.0.0")]
39+
#[must_use]
40+
#[inline]
41+
#[rustc_allow_incoherent_impl]
42+
pub fn from_raw_os_error(code: RawOsError) -> Error {
43+
Error::_from_raw_os_error(
44+
code,
45+
&alloc::io::OsFunctions {
46+
error_string: crate::sys::io::error_string,
47+
decode_error_kind: crate::sys::io::decode_error_kind,
48+
is_interrupted: crate::sys::io::is_interrupted,
49+
},
50+
)
51+
}
52+
53+
/// Returns the OS error that this error represents (if any).
54+
///
55+
/// If this [`Error`] was constructed via `last_os_error` or
56+
/// `from_raw_os_error`, then this function will return [`Some`], otherwise
57+
/// it will return [`None`].
58+
///
59+
/// # Examples
60+
///
61+
/// ```
62+
/// use std::io::{Error, ErrorKind};
63+
///
64+
/// fn print_os_error(err: &Error) {
65+
/// if let Some(raw_os_err) = err.raw_os_error() {
66+
/// println!("raw OS error: {raw_os_err:?}");
67+
/// } else {
68+
/// println!("Not an OS error");
69+
/// }
70+
/// }
71+
///
72+
/// fn main() {
73+
/// // Will print "raw OS error: ...".
74+
/// print_os_error(&Error::last_os_error());
75+
/// // Will print "Not an OS error".
76+
/// print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
77+
/// }
78+
/// ```
79+
#[stable(feature = "rust1", since = "1.0.0")]
80+
#[must_use]
81+
#[inline]
82+
#[rustc_allow_incoherent_impl]
83+
pub fn raw_os_error(&self) -> Option<RawOsError> {
84+
self._raw_os_error()
85+
}
86+
87+
/// Returns an error representing the last OS error which occurred.
88+
///
89+
/// This function reads the value of `errno` for the target platform (e.g.
90+
/// `GetLastError` on Windows) and will return a corresponding instance of
91+
/// [`Error`] for the error code.
92+
///
93+
/// This should be called immediately after a call to a platform function,
94+
/// otherwise the state of the error value is indeterminate. In particular,
95+
/// other standard library functions may call platform functions that may
96+
/// (or may not) reset the error value even if they succeed.
97+
///
98+
/// # Examples
99+
///
100+
/// ```
101+
/// use std::io::Error;
102+
///
103+
/// let os_error = Error::last_os_error();
104+
/// println!("last OS error: {os_error:?}");
105+
/// ```
106+
#[stable(feature = "rust1", since = "1.0.0")]
107+
#[doc(alias = "GetLastError")]
108+
#[doc(alias = "errno")]
109+
#[must_use]
110+
#[inline]
111+
#[rustc_allow_incoherent_impl]
112+
pub fn last_os_error() -> Error {
113+
Error::from_raw_os_error(crate::sys::io::errno())
114+
}
115+
}

library/std/src/io/error/tests.rs

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
use super::{Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage, const_error};
1+
use crate::io::{Error, ErrorKind, const_error};
22
use crate::sys::io::{decode_error_kind, error_string};
3-
use crate::{assert_matches, error, fmt};
3+
use crate::{error, fmt};
4+
5+
// Make sure that all these are used even when running tests
6+
#[cfg(test)]
7+
const _: () = {
8+
let _ = (crate::sys::io::errno, crate::sys::io::is_interrupted);
9+
};
410

511
#[test]
612
fn test_size() {
@@ -12,12 +18,9 @@ fn test_debug_error() {
1218
let code = 6;
1319
let msg = error_string(code);
1420
let kind = decode_error_kind(code);
15-
let err = Error {
16-
repr: Repr::new_custom(Box::new(Custom {
17-
kind: ErrorKind::InvalidInput,
18-
error: Box::new(Error { repr: super::Repr::new_os(code) }),
19-
})),
20-
};
21+
22+
let err = Error::new(ErrorKind::InvalidInput, Error::from_raw_os_error(code));
23+
2124
let expected = format!(
2225
"Custom {{ \
2326
kind: InvalidInput, \
@@ -30,6 +33,15 @@ fn test_debug_error() {
3033
code, kind, msg
3134
);
3235
assert_eq!(format!("{err:?}"), expected);
36+
37+
let err = Error::from(ErrorKind::AddrInUse);
38+
assert_eq!(format!("{err:?}"), "Kind(AddrInUse)");
39+
40+
let err = Error::READ_EXACT_EOF;
41+
assert_eq!(
42+
format!("{err:?}"),
43+
"Error { kind: UnexpectedEof, message: \"failed to fill whole buffer\" }"
44+
);
3345
}
3446

3547
#[test]
@@ -70,10 +82,6 @@ fn test_os_packing() {
7082
for code in -20..20 {
7183
let e = Error::from_raw_os_error(code);
7284
assert_eq!(e.raw_os_error(), Some(code));
73-
assert_matches!(
74-
e.repr.data(),
75-
ErrorData::Os(c) if c == code,
76-
);
7785
}
7886
}
7987

@@ -82,28 +90,18 @@ fn test_errorkind_packing() {
8290
assert_eq!(Error::from(ErrorKind::NotFound).kind(), ErrorKind::NotFound);
8391
assert_eq!(Error::from(ErrorKind::PermissionDenied).kind(), ErrorKind::PermissionDenied);
8492
assert_eq!(Error::from(ErrorKind::Uncategorized).kind(), ErrorKind::Uncategorized);
85-
// Check that the innards look like what we want.
86-
assert_matches!(
87-
Error::from(ErrorKind::OutOfMemory).repr.data(),
88-
ErrorData::Simple(ErrorKind::OutOfMemory),
89-
);
9093
}
9194

9295
#[test]
9396
fn test_simple_message_packing() {
94-
use super::ErrorKind::*;
95-
use super::SimpleMessage;
97+
use crate::io::ErrorKind::*;
9698
macro_rules! check_simple_msg {
9799
($err:expr, $kind:ident, $msg:literal) => {{
98100
let e = &$err;
99101
// Check that the public api is right.
100102
assert_eq!(e.kind(), $kind);
101103
assert!(format!("{e:?}").contains($msg));
102-
// and we got what we expected
103-
assert_matches!(
104-
e.repr.data(),
105-
ErrorData::SimpleMessage(SimpleMessage { kind: $kind, message: $msg })
106-
);
104+
assert!(format!("{e}").contains($msg));
107105
}};
108106
}
109107

@@ -126,19 +124,6 @@ impl fmt::Display for Bojji {
126124
}
127125
}
128126

129-
#[test]
130-
fn test_custom_error_packing() {
131-
use super::Custom;
132-
let test = Error::new(ErrorKind::Uncategorized, Bojji(true));
133-
assert_matches!(
134-
test.repr.data(),
135-
ErrorData::Custom(Custom {
136-
kind: ErrorKind::Uncategorized,
137-
error,
138-
}) if error.downcast_ref::<Bojji>().as_deref() == Some(&Bojji(true)),
139-
);
140-
}
141-
142127
#[derive(Debug)]
143128
struct E;
144129

@@ -181,11 +166,9 @@ fn test_std_io_error_downcast() {
181166
assert_eq!(kind, io_error.kind());
182167

183168
// Case 5: simple message
184-
const SIMPLE_MESSAGE: SimpleMessage =
185-
SimpleMessage { kind: ErrorKind::Other, message: "simple message error test" };
186-
let io_error = Error::from_static_message(&SIMPLE_MESSAGE);
169+
let io_error = const_error!(ErrorKind::Other, "simple message error test");
187170
let io_error = io_error.downcast::<E>().unwrap_err();
188171

189-
assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind());
190-
assert_eq!(SIMPLE_MESSAGE.message, format!("{io_error}"));
172+
assert_eq!(io_error.kind(), ErrorKind::Other);
173+
assert_eq!(format!("{io_error}"), "simple message error test");
191174
}

library/std/src/io/mod.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -297,19 +297,21 @@
297297
#[cfg(test)]
298298
mod tests;
299299

300+
#[unstable(feature = "raw_os_error_ty", issue = "107792")]
301+
pub use alloc::io::RawOsError;
302+
#[doc(hidden)]
303+
#[unstable(feature = "io_const_error_internals", issue = "none")]
304+
pub use alloc::io::SimpleMessage;
305+
#[unstable(feature = "io_const_error", issue = "133448")]
306+
pub use alloc::io::const_error;
307+
#[stable(feature = "rust1", since = "1.0.0")]
308+
pub use alloc::io::{Error, ErrorKind, Result};
300309
#[unstable(feature = "read_buf", issue = "78485")]
301310
pub use core::io::{BorrowedBuf, BorrowedCursor};
302311
use core::slice::memchr;
303312

304313
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
305314
pub use self::buffered::WriterPanicked;
306-
#[unstable(feature = "raw_os_error_ty", issue = "107792")]
307-
pub use self::error::RawOsError;
308-
#[doc(hidden)]
309-
#[unstable(feature = "io_const_error_internals", issue = "none")]
310-
pub use self::error::SimpleMessage;
311-
#[unstable(feature = "io_const_error", issue = "133448")]
312-
pub use self::error::const_error;
313315
#[stable(feature = "anonymous_pipe", since = "1.87.0")]
314316
pub use self::pipe::{PipeReader, PipeWriter, pipe};
315317
#[stable(feature = "is_terminal", since = "1.70.0")]
@@ -326,7 +328,6 @@ pub use self::{
326328
buffered::{BufReader, BufWriter, IntoInnerError, LineWriter},
327329
copy::copy,
328330
cursor::Cursor,
329-
error::{Error, ErrorKind, Result},
330331
stdio::{Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, stderr, stdin, stdout},
331332
util::{Empty, Repeat, Sink, empty, repeat, sink},
332333
};

library/std/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,14 @@
369369
//
370370
// Library features (alloc):
371371
// tidy-alphabetical-start
372+
#![feature(alloc_io)]
372373
#![feature(allocator_api)]
373374
#![feature(clone_from_ref)]
374375
#![feature(get_mut_unchecked)]
376+
#![feature(io_error_inprogress)]
377+
#![feature(io_error_internals)]
378+
#![feature(io_error_more)]
379+
#![feature(io_error_uncategorized)]
375380
#![feature(map_try_insert)]
376381
#![feature(slice_concat_trait)]
377382
#![feature(thin_box)]

library/std/src/sys/io/error/mod.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,3 @@ cfg_select! {
4848
pub use generic::*;
4949
}
5050
}
51-
52-
pub type RawOsError = cfg_select! {
53-
target_os = "uefi" => usize,
54-
_ => i32,
55-
};

0 commit comments

Comments
 (0)