From 7bdad89f950d374c128edffacd9872f7dbc72f78 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Wed, 9 Feb 2022 15:12:17 -0800 Subject: [PATCH 1/2] Stabilize Termination and ExitCode --- library/std/src/process.rs | 63 +++++++++++++------ library/test/src/lib.rs | 3 +- .../termination-trait-for-exitcode.rs | 1 - .../termination-trait-for-impl-termination.rs | 1 - 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 1f04890539604..a39793d9c220c 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1404,6 +1404,15 @@ impl From 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 // @@ -1636,8 +1645,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 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. @@ -1648,23 +1665,26 @@ 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` /// -/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937 +/// `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. #[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. /// /// 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. @@ -1672,7 +1692,7 @@ impl ExitCode { /// 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); } @@ -1684,14 +1704,18 @@ impl 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")] + #[unstable( + feature = "process_exitcode_internals", + reason = "exposed only for libstd", + issue = "none" + )] #[inline] 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 for ExitCode { /// Construct an exit code from an arbitrary u8 value. fn from(code: u8) -> Self { @@ -2031,7 +2055,7 @@ pub fn id() -> u32 { /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. #[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}`" @@ -2039,10 +2063,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 { @@ -2050,7 +2075,7 @@ impl Termination for () { } } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl Termination for Result<(), E> { fn report(self) -> ExitCode { match self { @@ -2060,14 +2085,14 @@ impl 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 Termination for Result { fn report(self) -> ExitCode { let Err(err) = self; @@ -2076,7 +2101,7 @@ impl Termination for Result { } } -#[unstable(feature = "termination_trait_lib", issue = "43301")] +#[stable(feature = "termination_trait_lib", since = "1.60.0")] impl Termination for Result { fn report(self) -> ExitCode { let Err(err) = self; @@ -2084,7 +2109,7 @@ impl Termination for Result { } } -#[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 { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 8fc2b4ed748c2..ff923528c39ce 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -19,8 +19,7 @@ #![feature(bench_black_box)] #![feature(internal_output_capture)] #![feature(staged_api)] -#![feature(termination_trait_lib)] -#![feature(process_exitcode_placeholder)] +#![feature(process_exitcode_internals)] #![feature(test)] #![feature(total_cmp)] diff --git a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs index 9c2270bf82752..6d4c1562053b6 100644 --- a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs +++ b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(process_exitcode_placeholder)] use std::process::ExitCode; diff --git a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs index 79cfba011c017..c06a135dcbc20 100644 --- a/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs +++ b/src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs @@ -1,4 +1,3 @@ // run-pass -#![feature(termination_trait_lib)] fn main() -> impl std::process::Termination { } From 97c58e8a87b0218a54dd0d58df03ffbc6d7fa10c Mon Sep 17 00:00:00 2001 From: Noa Date: Sun, 27 Mar 2022 18:38:01 -0500 Subject: [PATCH 2/2] Touch up ExitCode docs --- library/std/src/process.rs | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index a39793d9c220c..aea67873ed05f 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1648,8 +1648,8 @@ impl crate::error::Error for ExitStatusError {} /// 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 +/// `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 for /// ExitCode` for constructing other arbitrary exit codes. @@ -1673,13 +1673,31 @@ impl crate::error::Error for ExitStatusError {} /// 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 } +/// +/// fn main() -> ExitCode { +/// if !check_foo() { +/// return ExitCode::from(42); +/// } +/// +/// ExitCode::SUCCESS +/// } +/// ``` #[derive(Clone, Copy, Debug)] #[stable(feature = "process_exitcode", since = "1.60.0")] pub struct ExitCode(imp::ExitCode); #[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 @@ -1687,7 +1705,7 @@ impl ExitCode { #[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 @@ -1697,19 +1715,20 @@ impl ExitCode { } 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 + /// 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() } @@ -1717,7 +1736,7 @@ impl ExitCode { #[stable(feature = "process_exitcode", since = "1.60.0")] impl From 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)) }