diff options
| author | bors <bors@rust-lang.org> | 2022-03-29 21:01:45 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-03-29 21:01:45 +0000 |
| commit | 9c06e1ba47e1077725a950e0b5d1870a89c8b536 (patch) | |
| tree | cbbd2f53a1af15c37af805341655f7a82be2962d /library/std/src | |
| parent | 5e1d19d30723c287f049662474021f2b9a9894ce (diff) | |
| parent | 24715028a078fe592b546870c33de68d16a9ca3f (diff) | |
Auto merge of #95448 - Dylan-DPC:rollup-wpj5yto, r=Dylan-DPC
Rollup of 4 pull requests Successful merges: - #93840 (Stabilize Termination and ExitCode) - #95256 (Ensure io::Error's bitpacked repr doesn't accidentally impl UnwindSafe) - #95386 (Suggest wrapping patterns in enum variants) - #95437 (diagnostics: regression test for derive bounds) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/io/error/repr_bitpacked.rs | 20 | ||||
| -rw-r--r-- | library/std/src/process.rs | 92 |
2 files changed, 83 insertions, 29 deletions
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 1a0538f861a..208d5a80c5a 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -104,6 +104,7 @@ use super::{Custom, ErrorData, ErrorKind, SimpleMessage}; use alloc::boxed::Box; +use core::marker::PhantomData; use core::mem::{align_of, size_of}; use core::ptr::NonNull; @@ -114,8 +115,17 @@ const TAG_CUSTOM: usize = 0b01; const TAG_OS: usize = 0b10; const TAG_SIMPLE: usize = 0b11; +/// The internal representation. +/// +/// See the module docs for more, this is just a way to hack in a check that we +/// indeed are not unwind-safe. +/// +/// ```compile_fail,E0277 +/// fn is_unwind_safe<T: core::panic::UnwindSafe>() {} +/// is_unwind_safe::<std::io::Error>(); +/// ``` #[repr(transparent)] -pub(super) struct Repr(NonNull<()>); +pub(super) struct Repr(NonNull<()>, PhantomData<ErrorData<Box<Custom>>>); // All the types `Repr` stores internally are Send + Sync, and so is it. unsafe impl Send for Repr {} @@ -145,7 +155,7 @@ impl Repr { // box, and `TAG_CUSTOM` just... isn't zero -- it's `0b01`). Therefore, // `TAG_CUSTOM + p` isn't zero and so `tagged` can't be, and the // `new_unchecked` is safe. - let res = Self(unsafe { NonNull::new_unchecked(tagged) }); + let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed"); @@ -156,7 +166,7 @@ impl Repr { pub(super) fn new_os(code: i32) -> Self { let utagged = ((code as usize) << 32) | TAG_OS; // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0. - let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }); + let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!( @@ -170,7 +180,7 @@ impl Repr { pub(super) fn new_simple(kind: ErrorKind) -> Self { let utagged = ((kind as usize) << 32) | TAG_SIMPLE; // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0. - let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }); + let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!( @@ -184,7 +194,7 @@ impl Repr { #[inline] pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self { // Safety: References are never null. - Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }) + Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }, PhantomData) } #[inline] diff --git a/library/std/src/process.rs b/library/std/src/process.rs index b6edf8bca0a..d3c8d864b0c 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1417,6 +1417,15 @@ impl From<fs::File> for Stdio { /// For proper error reporting of failed processes, print the value of `ExitStatus` or /// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display). /// +/// # Differences from `ExitStatus` +/// +/// `ExitCode` is intended for terminating the currently running process, via +/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the +/// termination of a child process. These APIs are separate due to platform +/// compatibility differences and their expected usage; it is not generally +/// possible to exactly reproduce an ExitStatus from a child for the current +/// process after the fact. +/// /// [`status`]: Command::status /// [`wait`]: Child::wait // @@ -1649,8 +1658,16 @@ impl fmt::Display for ExitStatusError { #[unstable(feature = "exit_status_error", issue = "84908")] impl crate::error::Error for ExitStatusError {} -/// This type represents the status code a process can return to its -/// parent under normal termination. +/// This type represents the status code the current process can return +/// to its parent under normal termination. +/// +/// `ExitCode` is intended to be consumed only by the standard library (via +/// [`Termination::report()`]), and intentionally does not provide accessors like +/// `PartialEq`, `Eq`, or `Hash`. Instead the standard library provides the +/// canonical `SUCCESS` and `FAILURE` exit codes as well as `From<u8> for +/// ExitCode` for constructing other arbitrary exit codes. +/// +/// # Portability /// /// Numeric values used in this type don't have portable meanings, and /// different platforms may mask different amounts of them. @@ -1661,52 +1678,78 @@ impl crate::error::Error for ExitStatusError {} /// [`SUCCESS`]: ExitCode::SUCCESS /// [`FAILURE`]: ExitCode::FAILURE /// -/// **Warning**: While various forms of this were discussed in [RFC #1937], -/// it was ultimately cut from that RFC, and thus this type is more subject -/// to change even than the usual unstable item churn. +/// # Differences from `ExitStatus` +/// +/// `ExitCode` is intended for terminating the currently running process, via +/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the +/// termination of a child process. These APIs are separate due to platform +/// compatibility differences and their expected usage; it is not generally +/// possible to exactly reproduce an ExitStatus from a child for the current +/// process after the fact. +/// +/// # Examples +/// +/// `ExitCode` can be returned from the `main` function of a crate, as it implements +/// [`Termination`]: +/// +/// ``` +/// use std::process::ExitCode; +/// # fn check_foo() -> bool { true } /// -/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937 +/// fn main() -> ExitCode { +/// if !check_foo() { +/// return ExitCode::from(42); +/// } +/// +/// ExitCode::SUCCESS +/// } +/// ``` #[derive(Clone, Copy, Debug)] -#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] +#[stable(feature = "process_exitcode", since = "1.60.0")] pub struct ExitCode(imp::ExitCode); -#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] +#[stable(feature = "process_exitcode", since = "1.60.0")] impl ExitCode { - /// The canonical ExitCode for successful termination on this platform. + /// The canonical `ExitCode` for successful termination on this platform. /// /// Note that a `()`-returning `main` implicitly results in a successful /// termination, so there's no need to return this from `main` unless /// you're also returning other possible codes. - #[unstable(feature = "process_exitcode_placeholder", issue = "48711")] + #[stable(feature = "process_exitcode", since = "1.60.0")] pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS); - /// The canonical ExitCode for unsuccessful termination on this platform. + /// The canonical `ExitCode` for unsuccessful termination on this platform. /// /// If you're only returning this and `SUCCESS` from `main`, consider /// instead returning `Err(_)` and `Ok(())` respectively, which will /// return the same codes (but will also `eprintln!` the error). - #[unstable(feature = "process_exitcode_placeholder", issue = "48711")] + #[stable(feature = "process_exitcode", since = "1.60.0")] pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE); } impl ExitCode { - // This should not be stabilized when stabilizing ExitCode, we don't know that i32 will serve + // This is private/perma-unstable because ExitCode is opaque; we don't know that i32 will serve // all usecases, for example windows seems to use u32, unix uses the 8-15th bits of an i32, we // likely want to isolate users anything that could restrict the platform specific // representation of an ExitCode // // More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426 - /// Convert an ExitCode into an i32 - #[unstable(feature = "process_exitcode_placeholder", issue = "48711")] + /// Convert an `ExitCode` into an i32 + #[unstable( + feature = "process_exitcode_internals", + reason = "exposed only for libstd", + issue = "none" + )] #[inline] + #[doc(hidden)] pub fn to_i32(self) -> i32 { self.0.as_i32() } } -#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] +#[stable(feature = "process_exitcode", since = "1.60.0")] impl From<u8> for ExitCode { - /// Construct an exit code from an arbitrary u8 value. + /// Construct an `ExitCode` from an arbitrary u8 value. fn from(code: u8) -> Self { ExitCode(imp::ExitCode::from(code)) } @@ -2049,7 +2092,7 @@ pub fn id() -> u32 { /// standard library's runtime for convenience. Other runtimes are not required /// to provide similar functionality. #[cfg_attr(not(test), lang = "termination")] -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] #[rustc_on_unimplemented( message = "`main` has invalid return type `{Self}`", label = "`main` can only return types that implement `{Termination}`" @@ -2057,10 +2100,11 @@ pub fn id() -> u32 { pub trait Termination { /// Is called to get the representation of the value as status code. /// This status code is returned to the operating system. + #[stable(feature = "termination_trait_lib", since = "1.60.0")] fn report(self) -> ExitCode; } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl Termination for () { #[inline] fn report(self) -> ExitCode { @@ -2068,7 +2112,7 @@ impl Termination for () { } } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl<E: fmt::Debug> Termination for Result<(), E> { fn report(self) -> ExitCode { match self { @@ -2078,14 +2122,14 @@ impl<E: fmt::Debug> Termination for Result<(), E> { } } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl Termination for ! { fn report(self) -> ExitCode { self } } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl<E: fmt::Debug> Termination for Result<!, E> { fn report(self) -> ExitCode { let Err(err) = self; @@ -2094,7 +2138,7 @@ impl<E: fmt::Debug> Termination for Result<!, E> { } } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl<E: fmt::Debug> Termination for Result<Infallible, E> { fn report(self) -> ExitCode { let Err(err) = self; @@ -2102,7 +2146,7 @@ impl<E: fmt::Debug> Termination for Result<Infallible, E> { } } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl Termination for ExitCode { #[inline] fn report(self) -> ExitCode { |
