From 94e31c990b6ae60e5afbda5e3c8f301ba79df0a8 Mon Sep 17 00:00:00 2001 From: matt rice Date: Tue, 1 Feb 2022 15:14:04 -0800 Subject: [PATCH 1/2] impl Try for ExitStatus Currently just sys/unix is implemented. --- library/std/src/lib.rs | 1 + library/std/src/process.rs | 28 +++++++++++++++++++ .../std/src/sys/unix/process/process_unix.rs | 19 +++++++++++++ 3 files changed, 48 insertions(+) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6dc3fd9858451..8f6e86dbc3a44 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -300,6 +300,7 @@ #![feature(thin_box)] #![feature(toowned_clone_into)] #![feature(try_reserve_kind)] +#![feature(try_trait_v2)] #![feature(vec_into_raw_parts)] // // Library features (unwind): diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 771461a59089b..0d3c3de566593 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -112,10 +112,12 @@ use crate::fmt; use crate::fs; use crate::io::{self, IoSlice, IoSliceMut}; use crate::num::NonZeroI32; +use crate::ops::{ControlFlow, FromResidual, Try}; use crate::path::Path; use crate::str; use crate::sys::pipe::{read2, AnonPipe}; use crate::sys::process as imp; + #[stable(feature = "command_access", since = "1.57.0")] pub use crate::sys_common::process::CommandEnvs; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -1542,6 +1544,29 @@ impl fmt::Display for ExitStatus { } } +#[unstable(feature = "exit_status_error", issue = "84908")] +impl Try for ExitStatus { + type Output = (); + type Residual = Result; + + fn branch(self) -> ControlFlow { + self.0.try_branch() + } + + fn from_output((): ()) -> Self { + Self(imp::ExitStatus::zero_status()) + } +} + +#[unstable(feature = "exit_status_error", issue = "84908")] +impl FromResidual> for ExitStatus { + fn from_residual(residual: Result) -> Self { + match residual { + Err(exit_status_error) => exit_status_error.into(), + } + } +} + /// Allows extension traits within `std`. #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for ExitStatusError {} @@ -1574,6 +1599,9 @@ pub struct ExitStatusError(imp::ExitStatusError); #[unstable(feature = "exit_status_error", issue = "84908")] impl ExitStatusError { + pub(crate) fn new(exit_status_error: imp::ExitStatusError) -> Self { + ExitStatusError(exit_status_error) + } /// Reports the exit code, if applicable, from an `ExitStatusError`. /// /// In Unix terms the return value is the **exit status**: the value passed to `exit`, if the diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 23bb6d6c15f63..61c178a78acea 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -1,7 +1,9 @@ +use crate::convert::Infallible; use crate::fmt; use crate::io::{self, Error, ErrorKind}; use crate::mem; use crate::num::NonZeroI32; +use crate::ops::ControlFlow; use crate::ptr; use crate::sys; use crate::sys::cvt; @@ -647,6 +649,12 @@ impl ExitStatus { ExitStatus(status) } + // Returns a new 0 status, to avoid hard coding zero + // in crate::process::ExitStatus. + pub fn zero_status() -> ExitStatus { + ExitStatus(0) + } + fn exited(&self) -> bool { libc::WIFEXITED(self.0) } @@ -663,6 +671,17 @@ impl ExitStatus { } } + pub fn try_branch( + self, + ) -> ControlFlow, ()> { + match NonZero_c_int::try_from(self.0) { + Ok(failure) => ControlFlow::Break(Err(crate::process::ExitStatusError::new( + ExitStatusError(failure), + ))), + Err(_) => ControlFlow::Continue(()), + } + } + pub fn code(&self) -> Option { self.exited().then(|| libc::WEXITSTATUS(self.0)) } From f64d80843ce7d9a8171bca37a7031e707d4f2064 Mon Sep 17 00:00:00 2001 From: matt rice Date: Wed, 2 Feb 2022 03:55:51 -0800 Subject: [PATCH 2/2] windows implementation of impl Try for ExitStatus. Signed-off-by: matt rice --- library/std/src/sys/windows/process.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 8e5325b80e4a5..66cd42fb31fd9 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -5,6 +5,7 @@ mod tests; use crate::cmp; use crate::collections::BTreeMap; +use crate::convert::Infallible; use crate::env; use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use crate::ffi::{OsStr, OsString}; @@ -12,6 +13,7 @@ use crate::fmt; use crate::io::{self, Error, ErrorKind}; use crate::mem; use crate::num::NonZeroI32; +use crate::ops::ControlFlow; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle}; use crate::path::{Path, PathBuf}; @@ -675,6 +677,21 @@ impl ExitStatus { pub fn code(&self) -> Option { Some(self.0 as i32) } + + pub fn try_branch( + self, + ) -> ControlFlow, ()> { + match NonZeroDWORD::try_from(self.0) { + Ok(failure) => ControlFlow::Break(Err(crate::process::ExitStatusError::new( + ExitStatusError(failure), + ))), + Err(_) => ControlFlow::Continue(()), + } + } + + pub fn zero_status() -> ExitStatus { + ExitStatus(0) + } } /// Converts a raw `c::DWORD` to a type-safe `ExitStatus` by wrapping it without copying.