Stabilize Termination and ExitCode

This commit is contained in:
Jane Lusby 2022-02-09 15:12:17 -08:00
parent 75d9a0ae21
commit 7bdad89f95
4 changed files with 45 additions and 23 deletions

View File

@ -1404,6 +1404,15 @@ impl From<fs::File> for Stdio {
/// For proper error reporting of failed processes, print the value of `ExitStatus` or /// For proper error reporting of failed processes, print the value of `ExitStatus` or
/// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display). /// `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 /// [`status`]: Command::status
/// [`wait`]: Child::wait /// [`wait`]: Child::wait
// //
@ -1636,8 +1645,16 @@ impl fmt::Display for ExitStatusError {
#[unstable(feature = "exit_status_error", issue = "84908")] #[unstable(feature = "exit_status_error", issue = "84908")]
impl crate::error::Error for ExitStatusError {} impl crate::error::Error for ExitStatusError {}
/// This type represents the status code a process can return to its /// This type represents the status code the current process can return
/// parent under normal termination. /// 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 /// Numeric values used in this type don't have portable meanings, and
/// different platforms may mask different amounts of them. /// different platforms may mask different amounts of them.
@ -1648,23 +1665,26 @@ impl crate::error::Error for ExitStatusError {}
/// [`SUCCESS`]: ExitCode::SUCCESS /// [`SUCCESS`]: ExitCode::SUCCESS
/// [`FAILURE`]: ExitCode::FAILURE /// [`FAILURE`]: ExitCode::FAILURE
/// ///
/// **Warning**: While various forms of this were discussed in [RFC #1937], /// # Differences from `ExitStatus`
/// it was ultimately cut from that RFC, and thus this type is more subject
/// to change even than the usual unstable item churn.
/// ///
/// [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)] #[derive(Clone, Copy, Debug)]
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] #[stable(feature = "process_exitcode", since = "1.60.0")]
pub struct ExitCode(imp::ExitCode); pub struct ExitCode(imp::ExitCode);
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] #[stable(feature = "process_exitcode", since = "1.60.0")]
impl ExitCode { 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 /// Note that a `()`-returning `main` implicitly results in a successful
/// termination, so there's no need to return this from `main` unless /// termination, so there's no need to return this from `main` unless
/// you're also returning other possible codes. /// 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); 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.
@ -1672,7 +1692,7 @@ impl ExitCode {
/// If you're only returning this and `SUCCESS` from `main`, consider /// If you're only returning this and `SUCCESS` from `main`, consider
/// instead returning `Err(_)` and `Ok(())` respectively, which will /// instead returning `Err(_)` and `Ok(())` respectively, which will
/// return the same codes (but will also `eprintln!` the error). /// 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); 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 // 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_placeholder", issue = "48711")] #[unstable(
feature = "process_exitcode_internals",
reason = "exposed only for libstd",
issue = "none"
)]
#[inline] #[inline]
pub fn to_i32(self) -> i32 { pub fn to_i32(self) -> i32 {
self.0.as_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 { impl From<u8> for ExitCode {
/// Construct an exit code from an arbitrary u8 value. /// Construct an exit code from an arbitrary u8 value.
fn from(code: u8) -> Self { fn from(code: u8) -> Self {
@ -2031,7 +2055,7 @@ pub fn id() -> u32 {
/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
#[cfg_attr(not(test), lang = "termination")] #[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( #[rustc_on_unimplemented(
message = "`main` has invalid return type `{Self}`", message = "`main` has invalid return type `{Self}`",
label = "`main` can only return types that implement `{Termination}`" label = "`main` can only return types that implement `{Termination}`"
@ -2039,10 +2063,11 @@ pub fn id() -> u32 {
pub trait Termination { pub trait Termination {
/// Is called to get the representation of the value as status code. /// Is called to get the representation of the value as status code.
/// This status code is returned to the operating system. /// This status code is returned to the operating system.
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
fn report(self) -> ExitCode; fn report(self) -> ExitCode;
} }
#[unstable(feature = "termination_trait_lib", issue = "43301")] #[stable(feature = "termination_trait_lib", since = "1.60.0")]
impl Termination for () { impl Termination for () {
#[inline] #[inline]
fn report(self) -> ExitCode { 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<E: fmt::Debug> Termination for Result<(), E> { impl<E: fmt::Debug> Termination for Result<(), E> {
fn report(self) -> ExitCode { fn report(self) -> ExitCode {
match self { match self {
@ -2060,14 +2085,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 ! { impl Termination for ! {
fn report(self) -> ExitCode { fn report(self) -> ExitCode {
self 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> { impl<E: fmt::Debug> Termination for Result<!, E> {
fn report(self) -> ExitCode { fn report(self) -> ExitCode {
let Err(err) = self; let Err(err) = self;
@ -2076,7 +2101,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> { impl<E: fmt::Debug> Termination for Result<Infallible, E> {
fn report(self) -> ExitCode { fn report(self) -> ExitCode {
let Err(err) = self; let Err(err) = self;
@ -2084,7 +2109,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 { impl Termination for ExitCode {
#[inline] #[inline]
fn report(self) -> ExitCode { fn report(self) -> ExitCode {

View File

@ -19,8 +19,7 @@
#![feature(bench_black_box)] #![feature(bench_black_box)]
#![feature(internal_output_capture)] #![feature(internal_output_capture)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(termination_trait_lib)] #![feature(process_exitcode_internals)]
#![feature(process_exitcode_placeholder)]
#![feature(test)] #![feature(test)]
#![feature(total_cmp)] #![feature(total_cmp)]

View File

@ -1,5 +1,4 @@
// run-pass // run-pass
#![feature(process_exitcode_placeholder)]
use std::process::ExitCode; use std::process::ExitCode;

View File

@ -1,4 +1,3 @@
// run-pass // run-pass
#![feature(termination_trait_lib)]
fn main() -> impl std::process::Termination { } fn main() -> impl std::process::Termination { }