about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-05-13 18:29:13 +0000
committerbors <bors@rust-lang.org>2022-05-13 18:29:13 +0000
commit9ad4bde042cfaf56f7579160c60ebd8550a720ab (patch)
treec9d38555b21e450dabd3c23e12468185cffc533e
parenta7d6408b05912396618dfdcc9cc713d3ace2aa9a (diff)
parenta9e29d204e0d666b2a7724c15ffa24f988066eeb (diff)
downloadrust-9ad4bde042cfaf56f7579160c60ebd8550a720ab.tar.gz
rust-9ad4bde042cfaf56f7579160c60ebd8550a720ab.zip
Auto merge of #95356 - coolreader18:exitstatus-exit-method, r=<try>
ExitCode::exit_process() method

cc `@yaahc` / #93840

(eeek, hit ctrl-enter before I meant to and right after realizing the branch name was wrong. oh, well)

I feel like it makes sense to have the `exit(ExitCode)` function as a method or at least associated function on ExitCode, but maybe that would hurt discoverability? Probably not as much if it's at the top of the `process::exit()` documentation or something, but idk. Also very unsure about the name, I'd like something that communicates that you are exiting with *this* ExitCode, but with a method name being postfix it doesn't seem to flow. `code.exit_process_with()` ? `.exit_process_with_self()` ? Blech. Maybe it doesn't matter, since ideally just `code.exit()` or something would be clear simply by the name and single parameter but :shrug:

Also I'd like to touch up the `ExitCode` docs (which I did a bit here), but that would probably be good in a separate PR, right? Since I think the beta deadline is coming up.
-rw-r--r--library/std/src/process.rs84
1 files changed, 56 insertions, 28 deletions
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 771461a5908..6c5c08d0bea 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1725,6 +1725,49 @@ impl ExitCode {
     /// return the same codes (but will also `eprintln!` the error).
     #[stable(feature = "process_exitcode", since = "1.61.0")]
     pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
+
+    /// Exit the current process with the given `ExitCode`.
+    ///
+    /// Note that this has the same caveats as [`process::exit()`][exit], namely that this function
+    /// terminates the process immediately, so no destructors on the current stack or any other
+    /// thread's stack will be run. If a clean shutdown is needed, it is recommended to simply
+    /// return this ExitCode from the `main` function, as demonstrated in the [type
+    /// documentation](#examples).
+    ///
+    /// # Differences from `process::exit()`
+    ///
+    /// `process::exit()` accepts any `i32` value as the exit code for the process; however, there
+    /// are platforms that only use a subset of that value (see [`process::exit` platform-specific
+    /// behavior][exit#platform-specific-behavior]). `ExitCode` exists because of this; only
+    /// `ExitCode`s that are supported by a majority of our platforms can be created, so those
+    /// problems don't exist (as much) with this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(exitcode_exit_method)]
+    /// # use std::process::ExitCode;
+    /// # use std::fmt;
+    /// # enum UhOhError { GenericProblem, Specific, WithCode { exit_code: ExitCode, _x: () } }
+    /// # impl fmt::Display for UhOhError {
+    /// #     fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { unimplemented!() }
+    /// # }
+    /// // there's no way to gracefully recover from an UhOhError, so we just
+    /// // print a message and exit
+    /// fn handle_unrecoverable_error(err: UhOhError) -> ! {
+    ///     eprintln!("UH OH! {err}");
+    ///     let code = match err {
+    ///         UhOhError::GenericProblem => ExitCode::FAILURE,
+    ///         UhOhError::Specific => ExitCode::from(3),
+    ///         UhOhError::WithCode { exit_code, .. } => exit_code,
+    ///     };
+    ///     code.exit_process()
+    /// }
+    /// ```
+    #[unstable(feature = "exitcode_exit_method", issue = "none")]
+    pub fn exit_process(self) -> ! {
+        exit(self.to_i32())
+    }
 }
 
 impl ExitCode {
@@ -1944,7 +1987,17 @@ impl Child {
 /// process, no destructors on the current stack or any other thread's stack
 /// will be run. If a clean shutdown is needed it is recommended to only call
 /// this function at a known point where there are no more destructors left
-/// to run.
+/// to run; or, preferably, simply return a type implementing [`Termination`]
+/// (such as [`ExitCode`] or `Result`) from the `main` function and avoid this
+/// function altogether:
+///
+/// ```
+/// # use std::io::Error as MyError;
+/// fn main() -> Result<(), MyError> {
+///     // ...
+///     Ok(())
+/// }
+/// ```
 ///
 /// ## Platform-specific behavior
 ///
@@ -1952,39 +2005,14 @@ impl Child {
 /// will be visible to a parent process inspecting the exit code. On most
 /// Unix-like platforms, only the eight least-significant bits are considered.
 ///
-/// # Examples
-///
-/// Due to this function’s behavior regarding destructors, a conventional way
-/// to use the function is to extract the actual computation to another
-/// function and compute the exit code from its return value:
-///
-/// ```
-/// fn run_app() -> Result<(), ()> {
-///     // Application logic here
-///     Ok(())
-/// }
-///
-/// fn main() {
-///     std::process::exit(match run_app() {
-///         Ok(_) => 0,
-///         Err(err) => {
-///             eprintln!("error: {err:?}");
-///             1
-///         }
-///     });
-/// }
-/// ```
-///
-/// Due to [platform-specific behavior], the exit code for this example will be
-/// `0` on Linux, but `256` on Windows:
+/// For example, the exit code for this example will be `0` on Linux, but `256`
+/// on Windows:
 ///
 /// ```no_run
 /// use std::process;
 ///
 /// process::exit(0x0100);
 /// ```
-///
-/// [platform-specific behavior]: #platform-specific-behavior
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn exit(code: i32) -> ! {
     crate::rt::cleanup();