diff options
Diffstat (limited to 'library/std')
| -rw-r--r-- | library/std/src/ffi/mod.rs | 22 | ||||
| -rw-r--r-- | library/std/src/fs.rs | 6 | ||||
| -rw-r--r-- | library/std/src/io/error.rs | 62 | ||||
| -rw-r--r-- | library/std/src/io/error/repr_bitpacked.rs | 9 | ||||
| -rw-r--r-- | library/std/src/io/error/repr_unpacked.rs | 4 | ||||
| -rw-r--r-- | library/std/src/io/error/tests.rs | 53 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 3 | ||||
| -rw-r--r-- | library/std/src/thread/mod.rs | 2 |
8 files changed, 138 insertions, 23 deletions
diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 484f42dafc3..d987bf69b25 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -146,24 +146,10 @@ #![stable(feature = "rust1", since = "1.0.0")] -/// See [alloc::ffi::FromVecWithNulError]. -#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] -pub type FromVecWithNulError = alloc::ffi::FromVecWithNulError; -/// See [alloc::ffi::CString]. -#[stable(feature = "rust1", since = "1.0.0")] -pub type CString = alloc::ffi::CString; -/// See [alloc::ffi::IntoStringError]. -#[stable(feature = "rust1", since = "1.0.0")] -pub type IntoStringError = alloc::ffi::IntoStringError; -/// See [alloc::ffi::NulError]. -#[stable(feature = "rust1", since = "1.0.0")] -pub type NulError = alloc::ffi::NulError; -/// See [core::ffi::CStr]. -#[stable(feature = "rust1", since = "1.0.0")] -pub type CStr = core::ffi::CStr; -/// See [core::ffi::FromBytesWithNulError]. -#[stable(feature = "cstr_from_bytes", since = "1.10.0")] -pub type FromBytesWithNulError = core::ffi::FromBytesWithNulError; +#[stable(feature = "alloc_c_string", since = "1.64.0")] +pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError}; +#[stable(feature = "core_c_str", since = "1.64.0")] +pub use core::ffi::{CStr, FromBytesWithNulError}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::os_str::{OsStr, OsString}; diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f46997b807a..d799776548a 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -295,6 +295,9 @@ pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> { /// This function will create a file if it does not exist, /// and will entirely replace its contents if it does. /// +/// Depending on the platform, this function may fail if the +/// full directory path does not exist. +/// /// This is a convenience function for using [`File::create`] and [`write_all`] /// with fewer imports. /// @@ -349,6 +352,9 @@ impl File { /// This function will create a file if it does not exist, /// and will truncate it if it does. /// + /// Depending on the platform, this function may fail if the + /// full directory path does not exist. + /// /// See the [`OpenOptions::open`] function for more details. /// /// # Examples diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 4a50e647c64..ff7fdcae16f 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -795,6 +795,68 @@ impl Error { } } + /// Attempt to downgrade the inner error to `E` if any. + /// + /// If this [`Error`] was constructed via [`new`] then this function will + /// attempt to perform downgrade on it, otherwise it will return [`Err`]. + /// + /// If downgrade succeeds, it will return [`Ok`], otherwise it will also + /// return [`Err`]. + /// + /// [`new`]: Error::new + /// + /// # Examples + /// + /// ``` + /// #![feature(io_error_downcast)] + /// + /// use std::fmt; + /// use std::io; + /// use std::error::Error; + /// + /// #[derive(Debug)] + /// enum E { + /// Io(io::Error), + /// SomeOtherVariant, + /// } + /// + /// impl fmt::Display for E { + /// // ... + /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// # todo!() + /// # } + /// } + /// impl Error for E {} + /// + /// impl From<io::Error> for E { + /// fn from(err: io::Error) -> E { + /// err.downcast::<E>() + /// .map(|b| *b) + /// .unwrap_or_else(E::Io) + /// } + /// } + /// ``` + #[unstable(feature = "io_error_downcast", issue = "99262")] + pub fn downcast<E>(self) -> result::Result<Box<E>, Self> + where + E: error::Error + Send + Sync + 'static, + { + match self.repr.into_data() { + ErrorData::Custom(b) if b.error.is::<E>() => { + let res = (*b).error.downcast::<E>(); + + // downcast is a really trivial and is marked as inline, so + // it's likely be inlined here. + // + // And the compiler should be able to eliminate the branch + // that produces `Err` here since b.error.is::<E>() + // returns true. + Ok(res.unwrap()) + } + repr_data => Err(Self { repr: Repr::new(repr_data) }), + } + } + /// Returns the corresponding [`ErrorKind`] for this error. /// /// # Examples diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index e80068b46ab..292bf4826fd 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -132,6 +132,15 @@ unsafe impl Send for Repr {} unsafe impl Sync for Repr {} impl Repr { + pub(super) fn new(dat: ErrorData<Box<Custom>>) -> Self { + match dat { + ErrorData::Os(code) => Self::new_os(code), + ErrorData::Simple(kind) => Self::new_simple(kind), + ErrorData::SimpleMessage(simple_message) => Self::new_simple_message(simple_message), + ErrorData::Custom(b) => Self::new_custom(b), + } + } + pub(super) fn new_custom(b: Box<Custom>) -> Self { let p = Box::into_raw(b).cast::<u8>(); // Should only be possible if an allocator handed out a pointer with diff --git a/library/std/src/io/error/repr_unpacked.rs b/library/std/src/io/error/repr_unpacked.rs index 3729c039c42..d6ad55b99f5 100644 --- a/library/std/src/io/error/repr_unpacked.rs +++ b/library/std/src/io/error/repr_unpacked.rs @@ -10,6 +10,10 @@ type Inner = ErrorData<Box<Custom>>; pub(super) struct Repr(Inner); impl Repr { + #[inline] + pub(super) fn new(dat: ErrorData<Box<Custom>>) -> Self { + Self(dat) + } pub(super) fn new_custom(b: Box<Custom>) -> Self { Self(Inner::Custom(b)) } diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index 8d7877bcad3..c897a5e8701 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -1,4 +1,4 @@ -use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr}; +use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage}; use crate::assert_matches::assert_matches; use crate::error; use crate::fmt; @@ -141,3 +141,54 @@ fn test_custom_error_packing() { }) if error.downcast_ref::<Bojji>().as_deref() == Some(&Bojji(true)), ); } + +#[derive(Debug)] +struct E; + +impl fmt::Display for E { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + Ok(()) + } +} + +impl error::Error for E {} + +#[test] +fn test_std_io_error_downcast() { + // Case 1: custom error, downcast succeeds + let io_error = Error::new(ErrorKind::Other, Bojji(true)); + let e: Box<Bojji> = io_error.downcast().unwrap(); + assert!(e.0); + + // Case 2: custom error, downcast fails + let io_error = Error::new(ErrorKind::Other, Bojji(true)); + let io_error = io_error.downcast::<E>().unwrap_err(); + + // ensures that the custom error is intact + assert_eq!(ErrorKind::Other, io_error.kind()); + let e: Box<Bojji> = io_error.downcast().unwrap(); + assert!(e.0); + + // Case 3: os error + let errno = 20; + let io_error = Error::from_raw_os_error(errno); + let io_error = io_error.downcast::<E>().unwrap_err(); + + assert_eq!(errno, io_error.raw_os_error().unwrap()); + + // Case 4: simple + let kind = ErrorKind::OutOfMemory; + let io_error: Error = kind.into(); + let io_error = io_error.downcast::<E>().unwrap_err(); + + assert_eq!(kind, io_error.kind()); + + // Case 5: simple message + const SIMPLE_MESSAGE: SimpleMessage = + SimpleMessage { kind: ErrorKind::Other, message: "simple message error test" }; + let io_error = Error::from_static_message(&SIMPLE_MESSAGE); + let io_error = io_error.downcast::<E>().unwrap_err(); + + assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind()); + assert_eq!(SIMPLE_MESSAGE.message, &*format!("{io_error}")); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8fbc5e27d02..ab50845e2b2 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -264,7 +264,6 @@ #![feature(atomic_mut_ptr)] #![feature(char_error_internals)] #![feature(char_internals)] -#![feature(core_c_str)] #![feature(core_intrinsics)] #![feature(cstr_from_bytes_until_nul)] #![feature(cstr_internals)] @@ -297,8 +296,6 @@ // // Library features (alloc): #![feature(alloc_layout_extra)] -#![feature(alloc_c_string)] -#![feature(alloc_ffi)] #![feature(allocator_api)] #![feature(get_mut_unchecked)] #![feature(map_try_insert)] diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index c70ac8c9806..d28c7b58b20 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1114,7 +1114,7 @@ impl Thread { // Used only internally to construct a thread object without spawning // Panics if the name contains nuls. pub(crate) fn new(name: Option<CString>) -> Thread { - // We have to use `unsafe` here to constuct the `Parker` in-place, + // We have to use `unsafe` here to construct the `Parker` in-place, // which is required for the UNIX implementation. // // SAFETY: We pin the Arc immediately after creation, so its address never |
