Skip to content

Commit bba2a64

Browse files
authored
Rollup merge of #93840 - yaahc:termination-stabilization-celebration-station, r=joshtriplett
Stabilize Termination and ExitCode From #43301 This PR stabilizes the Termination trait and associated ExitCode type. It also adjusts the ExitCode feature flag to replace the placeholder flag with a more permanent name, as well as splitting off the `to_i32` method behind its own permanently unstable feature flag. This PR stabilizes the termination trait with the following signature: ```rust pub trait Termination { fn report(self) -> ExitCode; } ``` The existing impls of `Termination` are effectively already stable due to the prior stabilization of `?` in main. This PR also stabilizes the following APIs on exit code ```rust #[derive(Clone, Copy, Debug)] pub struct ExitCode(_); impl ExitCode { pub const SUCCESS: ExitCode; pub const FAILURE: ExitCode; } impl From<u8> for ExitCode { /* ... */ } ``` --- All of the previous blockers have been resolved. The main ones that were resolved recently are: * The trait's name: We decided against changing this since none of the alternatives seemed particularly compelling. Instead we decided to end the bikeshedding and stick with the current name. ([link to the discussion](https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Termination.2FExit.20Status.20Stabilization/near/269793887)) * Issues around platform specific representations: We resolved this issue by changing the return type of `report` from `i32` to the opaque type `ExitCode`. That way we can change the underlying representation without affecting the API, letting us offer full support for platform specific exit code APIs in the future. * Custom exit codes: We resolved this by adding `From<u8> for ExitCode`. We choose to only support u8 initially because it is the least common denominator between the sets of exit codes supported by our current platforms. In the future we anticipate adding platform specific extension traits to ExitCode for constructors from larger or negative numbers, as needed.
2 parents 5e1d19d + 97c58e8 commit bba2a64

File tree

4 files changed

+69
-28
lines changed

4 files changed

+69
-28
lines changed

library/std/src/process.rs

+68-24
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,15 @@ impl From<fs::File> for Stdio {
14171417
/// For proper error reporting of failed processes, print the value of `ExitStatus` or
14181418
/// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display).
14191419
///
1420+
/// # Differences from `ExitStatus`
1421+
///
1422+
/// `ExitCode` is intended for terminating the currently running process, via
1423+
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
1424+
/// termination of a child process. These APIs are separate due to platform
1425+
/// compatibility differences and their expected usage; it is not generally
1426+
/// possible to exactly reproduce an ExitStatus from a child for the current
1427+
/// process after the fact.
1428+
///
14201429
/// [`status`]: Command::status
14211430
/// [`wait`]: Child::wait
14221431
//
@@ -1649,8 +1658,16 @@ impl fmt::Display for ExitStatusError {
16491658
#[unstable(feature = "exit_status_error", issue = "84908")]
16501659
impl crate::error::Error for ExitStatusError {}
16511660

1652-
/// This type represents the status code a process can return to its
1653-
/// parent under normal termination.
1661+
/// This type represents the status code the current process can return
1662+
/// to its parent under normal termination.
1663+
///
1664+
/// `ExitCode` is intended to be consumed only by the standard library (via
1665+
/// [`Termination::report()`]), and intentionally does not provide accessors like
1666+
/// `PartialEq`, `Eq`, or `Hash`. Instead the standard library provides the
1667+
/// canonical `SUCCESS` and `FAILURE` exit codes as well as `From<u8> for
1668+
/// ExitCode` for constructing other arbitrary exit codes.
1669+
///
1670+
/// # Portability
16541671
///
16551672
/// Numeric values used in this type don't have portable meanings, and
16561673
/// different platforms may mask different amounts of them.
@@ -1661,52 +1678,78 @@ impl crate::error::Error for ExitStatusError {}
16611678
/// [`SUCCESS`]: ExitCode::SUCCESS
16621679
/// [`FAILURE`]: ExitCode::FAILURE
16631680
///
1664-
/// **Warning**: While various forms of this were discussed in [RFC #1937],
1665-
/// it was ultimately cut from that RFC, and thus this type is more subject
1666-
/// to change even than the usual unstable item churn.
1681+
/// # Differences from `ExitStatus`
1682+
///
1683+
/// `ExitCode` is intended for terminating the currently running process, via
1684+
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
1685+
/// termination of a child process. These APIs are separate due to platform
1686+
/// compatibility differences and their expected usage; it is not generally
1687+
/// possible to exactly reproduce an ExitStatus from a child for the current
1688+
/// process after the fact.
1689+
///
1690+
/// # Examples
1691+
///
1692+
/// `ExitCode` can be returned from the `main` function of a crate, as it implements
1693+
/// [`Termination`]:
1694+
///
1695+
/// ```
1696+
/// use std::process::ExitCode;
1697+
/// # fn check_foo() -> bool { true }
16671698
///
1668-
/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937
1699+
/// fn main() -> ExitCode {
1700+
/// if !check_foo() {
1701+
/// return ExitCode::from(42);
1702+
/// }
1703+
///
1704+
/// ExitCode::SUCCESS
1705+
/// }
1706+
/// ```
16691707
#[derive(Clone, Copy, Debug)]
1670-
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1708+
#[stable(feature = "process_exitcode", since = "1.60.0")]
16711709
pub struct ExitCode(imp::ExitCode);
16721710

1673-
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1711+
#[stable(feature = "process_exitcode", since = "1.60.0")]
16741712
impl ExitCode {
1675-
/// The canonical ExitCode for successful termination on this platform.
1713+
/// The canonical `ExitCode` for successful termination on this platform.
16761714
///
16771715
/// Note that a `()`-returning `main` implicitly results in a successful
16781716
/// termination, so there's no need to return this from `main` unless
16791717
/// you're also returning other possible codes.
1680-
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1718+
#[stable(feature = "process_exitcode", since = "1.60.0")]
16811719
pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
16821720

1683-
/// The canonical ExitCode for unsuccessful termination on this platform.
1721+
/// The canonical `ExitCode` for unsuccessful termination on this platform.
16841722
///
16851723
/// If you're only returning this and `SUCCESS` from `main`, consider
16861724
/// instead returning `Err(_)` and `Ok(())` respectively, which will
16871725
/// return the same codes (but will also `eprintln!` the error).
1688-
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1726+
#[stable(feature = "process_exitcode", since = "1.60.0")]
16891727
pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
16901728
}
16911729

16921730
impl ExitCode {
1693-
// This should not be stabilized when stabilizing ExitCode, we don't know that i32 will serve
1731+
// This is private/perma-unstable because ExitCode is opaque; we don't know that i32 will serve
16941732
// all usecases, for example windows seems to use u32, unix uses the 8-15th bits of an i32, we
16951733
// likely want to isolate users anything that could restrict the platform specific
16961734
// representation of an ExitCode
16971735
//
16981736
// More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426
1699-
/// Convert an ExitCode into an i32
1700-
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1737+
/// Convert an `ExitCode` into an i32
1738+
#[unstable(
1739+
feature = "process_exitcode_internals",
1740+
reason = "exposed only for libstd",
1741+
issue = "none"
1742+
)]
17011743
#[inline]
1744+
#[doc(hidden)]
17021745
pub fn to_i32(self) -> i32 {
17031746
self.0.as_i32()
17041747
}
17051748
}
17061749

1707-
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1750+
#[stable(feature = "process_exitcode", since = "1.60.0")]
17081751
impl From<u8> for ExitCode {
1709-
/// Construct an exit code from an arbitrary u8 value.
1752+
/// Construct an `ExitCode` from an arbitrary u8 value.
17101753
fn from(code: u8) -> Self {
17111754
ExitCode(imp::ExitCode::from(code))
17121755
}
@@ -2049,26 +2092,27 @@ pub fn id() -> u32 {
20492092
/// standard library's runtime for convenience. Other runtimes are not required
20502093
/// to provide similar functionality.
20512094
#[cfg_attr(not(test), lang = "termination")]
2052-
#[unstable(feature = "termination_trait_lib", issue = "43301")]
2095+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
20532096
#[rustc_on_unimplemented(
20542097
message = "`main` has invalid return type `{Self}`",
20552098
label = "`main` can only return types that implement `{Termination}`"
20562099
)]
20572100
pub trait Termination {
20582101
/// Is called to get the representation of the value as status code.
20592102
/// This status code is returned to the operating system.
2103+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
20602104
fn report(self) -> ExitCode;
20612105
}
20622106

2063-
#[unstable(feature = "termination_trait_lib", issue = "43301")]
2107+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
20642108
impl Termination for () {
20652109
#[inline]
20662110
fn report(self) -> ExitCode {
20672111
ExitCode::SUCCESS.report()
20682112
}
20692113
}
20702114

2071-
#[unstable(feature = "termination_trait_lib", issue = "43301")]
2115+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
20722116
impl<E: fmt::Debug> Termination for Result<(), E> {
20732117
fn report(self) -> ExitCode {
20742118
match self {
@@ -2078,14 +2122,14 @@ impl<E: fmt::Debug> Termination for Result<(), E> {
20782122
}
20792123
}
20802124

2081-
#[unstable(feature = "termination_trait_lib", issue = "43301")]
2125+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
20822126
impl Termination for ! {
20832127
fn report(self) -> ExitCode {
20842128
self
20852129
}
20862130
}
20872131

2088-
#[unstable(feature = "termination_trait_lib", issue = "43301")]
2132+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
20892133
impl<E: fmt::Debug> Termination for Result<!, E> {
20902134
fn report(self) -> ExitCode {
20912135
let Err(err) = self;
@@ -2094,15 +2138,15 @@ impl<E: fmt::Debug> Termination for Result<!, E> {
20942138
}
20952139
}
20962140

2097-
#[unstable(feature = "termination_trait_lib", issue = "43301")]
2141+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
20982142
impl<E: fmt::Debug> Termination for Result<Infallible, E> {
20992143
fn report(self) -> ExitCode {
21002144
let Err(err) = self;
21012145
Err::<!, _>(err).report()
21022146
}
21032147
}
21042148

2105-
#[unstable(feature = "termination_trait_lib", issue = "43301")]
2149+
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
21062150
impl Termination for ExitCode {
21072151
#[inline]
21082152
fn report(self) -> ExitCode {

library/test/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
#![feature(bench_black_box)]
2020
#![feature(internal_output_capture)]
2121
#![feature(staged_api)]
22-
#![feature(termination_trait_lib)]
23-
#![feature(process_exitcode_placeholder)]
22+
#![feature(process_exitcode_internals)]
2423
#![feature(test)]
2524
#![feature(total_cmp)]
2625

src/test/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// run-pass
2-
#![feature(process_exitcode_placeholder)]
32

43
use std::process::ExitCode;
54

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
// run-pass
2-
#![feature(termination_trait_lib)]
32

43
fn main() -> impl std::process::Termination { }

0 commit comments

Comments
 (0)