Skip to content

Commit

Permalink
Auto merge of #93442 - yaahc:Termination-abstraction, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
Change Termination::report return type to ExitCode

Related to #43301

The goal of this change is to minimize the forward compatibility risks in stabilizing Termination. By using the opaque type `ExitCode` instead of an `i32` we leave room for us to evolve the API over time to provide what cross-platform consistency we can / minimize footguns when working with exit codes, where as stabilizing on `i32` would limit what changes we could make in the future in how we represent and construct exit codes.
  • Loading branch information
bors committed Feb 1, 2022
2 parents ad88831 + 19db85d commit 2681f25
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 10 deletions.
31 changes: 23 additions & 8 deletions library/std/src/process.rs
Expand Up @@ -1676,6 +1676,21 @@ impl ExitCode {
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
// 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")]
#[inline]
pub fn to_i32(self) -> i32 {
self.0.as_i32()
}
}

impl Child {
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
/// error is returned.
Expand Down Expand Up @@ -2016,20 +2031,20 @@ 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.
fn report(self) -> i32;
fn report(self) -> ExitCode;
}

#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for () {
#[inline]
fn report(self) -> i32 {
fn report(self) -> ExitCode {
ExitCode::SUCCESS.report()
}
}

#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl<E: fmt::Debug> Termination for Result<(), E> {
fn report(self) -> i32 {
fn report(self) -> ExitCode {
match self {
Ok(()) => ().report(),
Err(err) => Err::<!, _>(err).report(),
Expand All @@ -2039,14 +2054,14 @@ impl<E: fmt::Debug> Termination for Result<(), E> {

#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for ! {
fn report(self) -> i32 {
fn report(self) -> ExitCode {
self
}
}

#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl<E: fmt::Debug> Termination for Result<!, E> {
fn report(self) -> i32 {
fn report(self) -> ExitCode {
let Err(err) = self;
eprintln!("Error: {:?}", err);
ExitCode::FAILURE.report()
Expand All @@ -2055,7 +2070,7 @@ impl<E: fmt::Debug> Termination for Result<!, E> {

#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl<E: fmt::Debug> Termination for Result<Infallible, E> {
fn report(self) -> i32 {
fn report(self) -> ExitCode {
let Err(err) = self;
Err::<!, _>(err).report()
}
Expand All @@ -2064,7 +2079,7 @@ impl<E: fmt::Debug> Termination for Result<Infallible, E> {
#[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for ExitCode {
#[inline]
fn report(self) -> i32 {
self.0.as_i32()
fn report(self) -> ExitCode {
self
}
}
2 changes: 1 addition & 1 deletion library/std/src/rt.rs
Expand Up @@ -142,7 +142,7 @@ fn lang_start<T: crate::process::Termination + 'static>(
argv: *const *const u8,
) -> isize {
let Ok(v) = lang_start_internal(
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report(),
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
argc,
argv,
);
Expand Down
3 changes: 2 additions & 1 deletion library/test/src/lib.rs
Expand Up @@ -20,6 +20,7 @@
#![feature(internal_output_capture)]
#![feature(staged_api)]
#![feature(termination_trait_lib)]
#![feature(process_exitcode_placeholder)]
#![feature(test)]
#![feature(total_cmp)]

Expand Down Expand Up @@ -182,7 +183,7 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
/// Tests is considered a failure. By default, invokes `report()`
/// and checks for a `0` result.
pub fn assert_test_result<T: Termination>(result: T) {
let code = result.report();
let code = result.report().to_i32();
assert_eq!(
code, 0,
"the test returned a termination value with a non-zero status code ({}) \
Expand Down

0 comments on commit 2681f25

Please sign in to comment.