Skip to content

Commit 7210e46

Browse files
committed
Auto merge of rust-lang#99315 - JohnTitor:rollup-77wzoc1, r=JohnTitor
Rollup of 7 pull requests Successful merges: - rust-lang#98387 (Add new unstable API `downcast` to `std::io::Error`) - rust-lang#98662 (Add std::fs::write documentation precision) - rust-lang#99253 (Remove FIXME from MIR `always_storage_live_locals`) - rust-lang#99264 (Fix typo in mod.rs) - rust-lang#99270 (Add `#[must_use]` to `Box::from_raw`) - rust-lang#99277 (Stabilize `core::ffi::CStr`, `alloc::ffi::CString`, and friends) - rust-lang#99307 (Add regression test for rust-lang#64401) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 5635158 + 202c11b commit 7210e46

File tree

19 files changed

+226
-39
lines changed

19 files changed

+226
-39
lines changed

compiler/rustc_mir_dataflow/src/storage.rs

-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ use rustc_middle::mir::{self, Local};
44
/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations.
55
///
66
/// These locals have fixed storage for the duration of the body.
7-
//
8-
// FIXME: Currently, we need to traverse the entire MIR to compute this. We should instead store it
9-
// as a field in the `LocalDecl` for each `Local`.
107
pub fn always_storage_live_locals(body: &mir::Body<'_>) -> BitSet<Local> {
118
let mut always_live_locals = BitSet::new_filled(body.local_decls.len());
129

library/alloc/src/boxed.rs

+1
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,7 @@ impl<T: ?Sized> Box<T> {
949949
/// [`Layout`]: crate::Layout
950950
#[stable(feature = "box_raw", since = "1.4.0")]
951951
#[inline]
952+
#[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `Box`"]
952953
pub unsafe fn from_raw(raw: *mut T) -> Self {
953954
unsafe { Self::from_raw_in(raw, Global) }
954955
}

library/alloc/src/ffi/c_str.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ use crate::sync::Arc;
108108
/// and other memory errors.
109109
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
110110
#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")]
111-
#[unstable(feature = "alloc_c_string", issue = "94079")]
111+
#[stable(feature = "alloc_c_string", since = "1.64.0")]
112112
pub struct CString {
113113
// Invariant 1: the slice ends with a zero byte and has a length of at least one.
114114
// Invariant 2: the slice contains only one zero byte.
@@ -132,7 +132,7 @@ pub struct CString {
132132
/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err();
133133
/// ```
134134
#[derive(Clone, PartialEq, Eq, Debug)]
135-
#[unstable(feature = "alloc_c_string", issue = "94079")]
135+
#[stable(feature = "alloc_c_string", since = "1.64.0")]
136136
pub struct NulError(usize, Vec<u8>);
137137

138138
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -157,7 +157,7 @@ enum FromBytesWithNulErrorKind {
157157
/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err();
158158
/// ```
159159
#[derive(Clone, PartialEq, Eq, Debug)]
160-
#[unstable(feature = "alloc_c_string", issue = "94079")]
160+
#[stable(feature = "alloc_c_string", since = "1.64.0")]
161161
pub struct FromVecWithNulError {
162162
error_kind: FromBytesWithNulErrorKind,
163163
bytes: Vec<u8>,
@@ -223,7 +223,7 @@ impl FromVecWithNulError {
223223
/// This `struct` is created by [`CString::into_string()`]. See
224224
/// its documentation for more.
225225
#[derive(Clone, PartialEq, Eq, Debug)]
226-
#[unstable(feature = "alloc_c_string", issue = "94079")]
226+
#[stable(feature = "alloc_c_string", since = "1.64.0")]
227227
pub struct IntoStringError {
228228
inner: CString,
229229
error: Utf8Error,

library/alloc/src/ffi/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@
7878
//! [`String`]: crate::string::String
7979
//! [`CStr`]: core::ffi::CStr
8080
81-
#![unstable(feature = "alloc_ffi", issue = "94079")]
81+
#![stable(feature = "alloc_ffi", since = "1.64.0")]
8282

83-
#[unstable(feature = "alloc_c_string", issue = "94079")]
83+
#[stable(feature = "alloc_c_string", since = "1.64.0")]
8484
pub use self::c_str::FromVecWithNulError;
85-
#[unstable(feature = "alloc_c_string", issue = "94079")]
85+
#[stable(feature = "alloc_c_string", since = "1.64.0")]
8686
pub use self::c_str::{CString, IntoStringError, NulError};
8787

8888
mod c_str;

library/alloc/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
#![allow(explicit_outlives_requirements)]
8787
//
8888
// Library features:
89-
#![cfg_attr(not(no_global_oom_handling), feature(alloc_c_string))]
9089
#![feature(alloc_layout_extra)]
9190
#![feature(allocator_api)]
9291
#![feature(array_chunks)]
@@ -106,7 +105,6 @@
106105
#![feature(const_maybe_uninit_write)]
107106
#![feature(const_maybe_uninit_as_mut_ptr)]
108107
#![feature(const_refs_to_cell)]
109-
#![feature(core_c_str)]
110108
#![feature(core_intrinsics)]
111109
#![feature(const_eval_select)]
112110
#![feature(const_pin)]

library/alloc/tests/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#![feature(const_nonnull_slice_from_raw_parts)]
1212
#![feature(const_ptr_write)]
1313
#![feature(const_try)]
14-
#![feature(core_c_str)]
1514
#![feature(core_intrinsics)]
1615
#![feature(drain_filter)]
1716
#![feature(exact_size_is_empty)]

library/core/src/ffi/c_str.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use crate::str;
7676
/// [str]: prim@str "str"
7777
#[derive(Hash)]
7878
#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")]
79-
#[unstable(feature = "core_c_str", issue = "94079")]
79+
#[stable(feature = "core_c_str", since = "1.64.0")]
8080
#[rustc_has_incoherent_inherent_impls]
8181
// FIXME:
8282
// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
@@ -108,7 +108,7 @@ pub struct CStr {
108108
/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
109109
/// ```
110110
#[derive(Clone, PartialEq, Eq, Debug)]
111-
#[unstable(feature = "core_c_str", issue = "94079")]
111+
#[stable(feature = "core_c_str", since = "1.64.0")]
112112
pub struct FromBytesWithNulError {
113113
kind: FromBytesWithNulErrorKind,
114114
}

library/core/src/ffi/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::marker::PhantomData;
1414
use crate::num::*;
1515
use crate::ops::{Deref, DerefMut};
1616

17-
#[unstable(feature = "core_c_str", issue = "94079")]
17+
#[stable(feature = "core_c_str", since = "1.64.0")]
1818
pub use self::c_str::{CStr, FromBytesUntilNulError, FromBytesWithNulError};
1919

2020
mod c_str;

library/std/src/ffi/mod.rs

+4-18
Original file line numberDiff line numberDiff line change
@@ -146,24 +146,10 @@
146146
147147
#![stable(feature = "rust1", since = "1.0.0")]
148148

149-
/// See [alloc::ffi::FromVecWithNulError].
150-
#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
151-
pub type FromVecWithNulError = alloc::ffi::FromVecWithNulError;
152-
/// See [alloc::ffi::CString].
153-
#[stable(feature = "rust1", since = "1.0.0")]
154-
pub type CString = alloc::ffi::CString;
155-
/// See [alloc::ffi::IntoStringError].
156-
#[stable(feature = "rust1", since = "1.0.0")]
157-
pub type IntoStringError = alloc::ffi::IntoStringError;
158-
/// See [alloc::ffi::NulError].
159-
#[stable(feature = "rust1", since = "1.0.0")]
160-
pub type NulError = alloc::ffi::NulError;
161-
/// See [core::ffi::CStr].
162-
#[stable(feature = "rust1", since = "1.0.0")]
163-
pub type CStr = core::ffi::CStr;
164-
/// See [core::ffi::FromBytesWithNulError].
165-
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
166-
pub type FromBytesWithNulError = core::ffi::FromBytesWithNulError;
149+
#[stable(feature = "alloc_c_string", since = "1.64.0")]
150+
pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError};
151+
#[stable(feature = "core_c_str", since = "1.64.0")]
152+
pub use core::ffi::{CStr, FromBytesWithNulError};
167153

168154
#[stable(feature = "rust1", since = "1.0.0")]
169155
pub use self::os_str::{OsStr, OsString};

library/std/src/fs.rs

+6
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
295295
/// This function will create a file if it does not exist,
296296
/// and will entirely replace its contents if it does.
297297
///
298+
/// Depending on the platform, this function may fail if the
299+
/// full directory path does not exist.
300+
///
298301
/// This is a convenience function for using [`File::create`] and [`write_all`]
299302
/// with fewer imports.
300303
///
@@ -349,6 +352,9 @@ impl File {
349352
/// This function will create a file if it does not exist,
350353
/// and will truncate it if it does.
351354
///
355+
/// Depending on the platform, this function may fail if the
356+
/// full directory path does not exist.
357+
///
352358
/// See the [`OpenOptions::open`] function for more details.
353359
///
354360
/// # Examples

library/std/src/io/error.rs

+62
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,68 @@ impl Error {
795795
}
796796
}
797797

798+
/// Attempt to downgrade the inner error to `E` if any.
799+
///
800+
/// If this [`Error`] was constructed via [`new`] then this function will
801+
/// attempt to perform downgrade on it, otherwise it will return [`Err`].
802+
///
803+
/// If downgrade succeeds, it will return [`Ok`], otherwise it will also
804+
/// return [`Err`].
805+
///
806+
/// [`new`]: Error::new
807+
///
808+
/// # Examples
809+
///
810+
/// ```
811+
/// #![feature(io_error_downcast)]
812+
///
813+
/// use std::fmt;
814+
/// use std::io;
815+
/// use std::error::Error;
816+
///
817+
/// #[derive(Debug)]
818+
/// enum E {
819+
/// Io(io::Error),
820+
/// SomeOtherVariant,
821+
/// }
822+
///
823+
/// impl fmt::Display for E {
824+
/// // ...
825+
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
826+
/// # todo!()
827+
/// # }
828+
/// }
829+
/// impl Error for E {}
830+
///
831+
/// impl From<io::Error> for E {
832+
/// fn from(err: io::Error) -> E {
833+
/// err.downcast::<E>()
834+
/// .map(|b| *b)
835+
/// .unwrap_or_else(E::Io)
836+
/// }
837+
/// }
838+
/// ```
839+
#[unstable(feature = "io_error_downcast", issue = "99262")]
840+
pub fn downcast<E>(self) -> result::Result<Box<E>, Self>
841+
where
842+
E: error::Error + Send + Sync + 'static,
843+
{
844+
match self.repr.into_data() {
845+
ErrorData::Custom(b) if b.error.is::<E>() => {
846+
let res = (*b).error.downcast::<E>();
847+
848+
// downcast is a really trivial and is marked as inline, so
849+
// it's likely be inlined here.
850+
//
851+
// And the compiler should be able to eliminate the branch
852+
// that produces `Err` here since b.error.is::<E>()
853+
// returns true.
854+
Ok(res.unwrap())
855+
}
856+
repr_data => Err(Self { repr: Repr::new(repr_data) }),
857+
}
858+
}
859+
798860
/// Returns the corresponding [`ErrorKind`] for this error.
799861
///
800862
/// # Examples

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

+9
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,15 @@ unsafe impl Send for Repr {}
132132
unsafe impl Sync for Repr {}
133133

134134
impl Repr {
135+
pub(super) fn new(dat: ErrorData<Box<Custom>>) -> Self {
136+
match dat {
137+
ErrorData::Os(code) => Self::new_os(code),
138+
ErrorData::Simple(kind) => Self::new_simple(kind),
139+
ErrorData::SimpleMessage(simple_message) => Self::new_simple_message(simple_message),
140+
ErrorData::Custom(b) => Self::new_custom(b),
141+
}
142+
}
143+
135144
pub(super) fn new_custom(b: Box<Custom>) -> Self {
136145
let p = Box::into_raw(b).cast::<u8>();
137146
// Should only be possible if an allocator handed out a pointer with

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

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ type Inner = ErrorData<Box<Custom>>;
1010
pub(super) struct Repr(Inner);
1111

1212
impl Repr {
13+
#[inline]
14+
pub(super) fn new(dat: ErrorData<Box<Custom>>) -> Self {
15+
Self(dat)
16+
}
1317
pub(super) fn new_custom(b: Box<Custom>) -> Self {
1418
Self(Inner::Custom(b))
1519
}

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

+52-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr};
1+
use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage};
22
use crate::assert_matches::assert_matches;
33
use crate::error;
44
use crate::fmt;
@@ -141,3 +141,54 @@ fn test_custom_error_packing() {
141141
}) if error.downcast_ref::<Bojji>().as_deref() == Some(&Bojji(true)),
142142
);
143143
}
144+
145+
#[derive(Debug)]
146+
struct E;
147+
148+
impl fmt::Display for E {
149+
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
150+
Ok(())
151+
}
152+
}
153+
154+
impl error::Error for E {}
155+
156+
#[test]
157+
fn test_std_io_error_downcast() {
158+
// Case 1: custom error, downcast succeeds
159+
let io_error = Error::new(ErrorKind::Other, Bojji(true));
160+
let e: Box<Bojji> = io_error.downcast().unwrap();
161+
assert!(e.0);
162+
163+
// Case 2: custom error, downcast fails
164+
let io_error = Error::new(ErrorKind::Other, Bojji(true));
165+
let io_error = io_error.downcast::<E>().unwrap_err();
166+
167+
// ensures that the custom error is intact
168+
assert_eq!(ErrorKind::Other, io_error.kind());
169+
let e: Box<Bojji> = io_error.downcast().unwrap();
170+
assert!(e.0);
171+
172+
// Case 3: os error
173+
let errno = 20;
174+
let io_error = Error::from_raw_os_error(errno);
175+
let io_error = io_error.downcast::<E>().unwrap_err();
176+
177+
assert_eq!(errno, io_error.raw_os_error().unwrap());
178+
179+
// Case 4: simple
180+
let kind = ErrorKind::OutOfMemory;
181+
let io_error: Error = kind.into();
182+
let io_error = io_error.downcast::<E>().unwrap_err();
183+
184+
assert_eq!(kind, io_error.kind());
185+
186+
// Case 5: simple message
187+
const SIMPLE_MESSAGE: SimpleMessage =
188+
SimpleMessage { kind: ErrorKind::Other, message: "simple message error test" };
189+
let io_error = Error::from_static_message(&SIMPLE_MESSAGE);
190+
let io_error = io_error.downcast::<E>().unwrap_err();
191+
192+
assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind());
193+
assert_eq!(SIMPLE_MESSAGE.message, &*format!("{io_error}"));
194+
}

library/std/src/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,6 @@
264264
#![feature(atomic_mut_ptr)]
265265
#![feature(char_error_internals)]
266266
#![feature(char_internals)]
267-
#![feature(core_c_str)]
268267
#![feature(core_intrinsics)]
269268
#![feature(cstr_from_bytes_until_nul)]
270269
#![feature(cstr_internals)]
@@ -297,8 +296,6 @@
297296
//
298297
// Library features (alloc):
299298
#![feature(alloc_layout_extra)]
300-
#![feature(alloc_c_string)]
301-
#![feature(alloc_ffi)]
302299
#![feature(allocator_api)]
303300
#![feature(get_mut_unchecked)]
304301
#![feature(map_try_insert)]

library/std/src/thread/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ impl Thread {
11141114
// Used only internally to construct a thread object without spawning
11151115
// Panics if the name contains nuls.
11161116
pub(crate) fn new(name: Option<CString>) -> Thread {
1117-
// We have to use `unsafe` here to constuct the `Parker` in-place,
1117+
// We have to use `unsafe` here to construct the `Parker` in-place,
11181118
// which is required for the UNIX implementation.
11191119
//
11201120
// SAFETY: We pin the Arc immediately after creation, so its address never

0 commit comments

Comments
 (0)