Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add #[must_use] to process::Command, process::Child and process::ExitStatus #81452

Closed
wants to merge 12 commits into from

Conversation

ijackson
Copy link
Contributor

@ijackson ijackson commented Jan 27, 2021

Motivation

These three critical types in std::process should all be #[must_use]. Failure to use a Command is hopefully fairly obvious but it seems friendly to mark this one for the same reason as futures.

Failure to use a Child or ExitStatus are more serious.

On unix, failure to use a Child leaks the process. It continues running in parallel, even after we have exited (or crashed), possibly interfering with the user's terminal or driveling nonsense into a logfile long after the original event. In a long-running process, the child will become a zombie when it exits, and accumulation of zombies can prevent the spawning of new children. IDK what failure to use a Child does on Windows but the docs are not encouraging.

Failure to use an ExitStatus is the kind of error-handling bug Rust usually tries to save us from.

Contents of this MR

The main aim is just to mark these three types #[must_use]. However, I reviewed the documentation and it was missing two of the problems with leaking Child. I also felt .spawn() ought to direct the reader to .status().

More worryingly, the #[must_use] changes revealed that most of the examples were broken. Most of them leak the Child and nearly none of them check the exit status. So I fixed that.

Bugs this revealed in other parts of rust-lang/rust, outside the stdlib

The bootstrap wrapper for rustc ignored the status of the on_fail command. Although failing to run it at all produces a panic, I felt that was a bit much for if it simply fails. So I chose to print a warning to stderr. We are already failing here, so the shim will exit nonzero in any case.

Two tests in src/ui/test failed to check the exit status; in one case this is a clear bug.

The runtest wrapper failed to check the exit status from two of its invocations of adb.

Concern

During a pre-RFC discussion I was told that adding a #[must_use] is not considered a breaking change because it's only a lint.

But I worry that this imay be too disruptive a change, given the problems in the stdlib examples themselves, and the rest of the lang tree.

On the other hand: almost all of the things that this found in the stdlib were actual bugs - bugs which would have been quite serious in deployed code. Perhaps it is better to do our community the service of highlighting these problems rather than tolerating them.

A friend observed that adding these #[must_use] would be "doing the community a favour, but I'm not sure they'll enjoy it".

@rust-highfive
Copy link
Collaborator

r? @KodrAus

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 27, 2021
@ijackson
Copy link
Contributor Author

@rustbot modify labels +T-libs

Hrm, doesn't seem like this has managed to link the issues #70186 and #73127 which ought to be closed if this MR is merged.

I should also mention my subprocess tracking issue #73131.

@rustbot rustbot added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jan 27, 2021
@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
Successfully built b5a26c80938d
Successfully tagged rust-ci:latest
Built container sha256:b5a26c80938de4f3144682676d2bdee379594261097c5a667901c21abecfcc5e
Uploading finished image to https://ci-caches.rust-lang.org/docker/80afe504501370b4d310121e20e04a989f302196b07831c4375b96e05bc067556c2046e20ab2062b28a9dc9b2ae132b37d419cc55a065dfcd25501527e829ab9
upload failed: - to s3://rust-lang-ci-sccache2/docker/80afe504501370b4d310121e20e04a989f302196b07831c4375b96e05bc067556c2046e20ab2062b28a9dc9b2ae132b37d419cc55a065dfcd25501527e829ab9 Unable to locate credentials
[CI_JOB_NAME=mingw-check]
---
    Checking merge v0.1.0
    Checking serde v1.0.118
    Checking toml v0.5.7
    Checking serde_json v1.0.59
error: unused `ExitStatus` that must be used
   --> src/bootstrap/bin/rustc.rs:182:9
    |
182 |         on_fail.status().expect("Could not run the on_fail command");
    |
    |
    = note: `-D unused-must-use` implied by `-D warnings`
    = note: this ExitStatus might represent an error that should be checked and handled
error: aborting due to previous error

error: could not compile `bootstrap`

@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
configure: rust.channel         := nightly
configure: rust.debug-assertions := True
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
   Compiling tracing v0.1.19
   Compiling tracing-subscriber v0.2.13
   Compiling rustfix v0.5.1
   Compiling compiletest v0.0.0 (/checkout/src/tools/compiletest)
error: unused `ExitStatus` that must be used
    |
    |
872 | /             Command::new(adb_path)
873 | |                 .arg("push")
874 | |                 .arg(&exe_file)
875 | |                 .arg(&self.config.adb_test_dir)
876 | |                 .status()
877 | |                 .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
    |
    |
    = note: `-D unused-must-use` implied by `-D warnings`
    = note: this ExitStatus might represent an error that should be checked and handled

error: unused `ExitStatus` that must be used
    |
    |
879 | /             Command::new(adb_path)
880 | |                 .args(&["forward", "tcp:5039", "tcp:5039"])
881 | |                 .status()
882 | |                 .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
    |
    = note: this ExitStatus might represent an error that should be checked and handled

error: aborting due to 2 previous errors

@ijackson
Copy link
Contributor Author

Well there are quite a lot of these, aren't there!

@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
configure: rust.channel         := nightly
configure: rust.debug-assertions := True
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
   Compiling compiletest v0.0.0 (/checkout/src/tools/compiletest)
error: mismatched closing delimiter: `)`
   --> src/tools/compiletest/src/runtest.rs:878:75
    |
878 |             if !status.success() { panic("Program failed `{:}`", adb_path));

error: mismatched closing delimiter: `)`
   --> src/tools/compiletest/src/runtest.rs:884:75
    |
    |
884 |             if !status.success() { panic("Program failed `{:}`", adb_path));


error[E0423]: expected function, found macro `panic`
    |
    |
878 |             if !status.success() { panic("Program failed `{:}`", adb_path));
    |
    |
help: use `!` to invoke the macro
    |
878 |             if !status.success() { panic!("Program failed `{:}`", adb_path));
help: consider importing this function instead
    |
3   | use core::panicking::panic;
    |
    |

error[E0423]: expected function, found macro `panic`
    |
    |
884 |             if !status.success() { panic("Program failed `{:}`", adb_path));
    |
    |
help: use `!` to invoke the macro
    |
884 |             if !status.success() { panic!("Program failed `{:}`", adb_path));
help: consider importing this function instead
    |
3   | use core::panicking::panic;
    |

@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
configure: rust.channel         := nightly
configure: rust.debug-assertions := True
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
   Compiling compiletest v0.0.0 (/checkout/src/tools/compiletest)
error: mismatched closing delimiter: `)`
   --> src/tools/compiletest/src/runtest.rs:878:76
    |
878 |             if !status.success() { panic!("Program failed `{:}`", adb_path));

error: mismatched closing delimiter: `)`
   --> src/tools/compiletest/src/runtest.rs:884:76
    |
    |
884 |             if !status.success() { panic!("Program failed `{:}`", adb_path));

error: aborting due to 2 previous errors

error: could not compile `compiletest`

@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
configure: rust.channel         := nightly
configure: rust.debug-assertions := True
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
skip untracked path cpu-usage.csv during rustfmt invocations
skip untracked path src/doc/book/ during rustfmt invocations
skip untracked path src/doc/rust-by-example/ during rustfmt invocations
skip untracked path src/llvm-project/ during rustfmt invocations
Diff in /checkout/src/tools/compiletest/src/runtest.rs at line 875:
                 .arg(&self.config.adb_test_dir)
                 .status()
                 .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
-            if !status.success() { panic!("Program failed `{:}`", adb_path); }
+            if !status.success() {
+                panic!("Program failed `{:}`", adb_path);
 
 
             let status = Command::new(adb_path)
                 .args(&["forward", "tcp:5039", "tcp:5039"])
Diff in /checkout/src/tools/compiletest/src/runtest.rs at line 882:
                 .status()
                 .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
-            if !status.success() { panic!("Program failed `{:}`", adb_path); }
+            if !status.success() {
+                panic!("Program failed `{:}`", adb_path);
 
 
             let adb_arg = format!(
                 "export LD_LIBRARY_PATH={}; \
Running `"/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/rustfmt" "--config-path" "/checkout" "--edition" "2018" "--unstable-features" "--skip-children" "--check" "/checkout/src/tools/compiletest/src/runtest.rs"` failed.
If you're running `tidy`, try again with `--bless`. Or, if you just want to format code, run `./x.py fmt` instead.
Build completed unsuccessfully in 0:00:21

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-9 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
failures:

---- [ui] ui/fds-are-cloexec.rs stdout ----
normalized stderr:
warning: unused `ExitStatus` that must be used
  --> $DIR/fds-are-cloexec.rs:69:5
   |
LL |     child.wait().unwrap();
   |
   = note: `#[warn(unused_must_use)]` on by default
   = note: this ExitStatus might represent an error that should be checked and handled


warning: 1 warning emitted




The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/fds-are-cloexec/fds-are-cloexec.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args fds-are-cloexec.rs`
error: 1 errors occurred comparing output.
status: exit code: 0
status: exit code: 0
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/fds-are-cloexec.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zemit-future-incompat-report" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/fds-are-cloexec/a" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/fds-are-cloexec/auxiliary"
------------------------------------------
Some tests failed in compiletest suite=ui mode=ui host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu

------------------------------------------
------------------------------------------
stderr:
------------------------------------------
warning: unused `ExitStatus` that must be used
   |
   |
LL |     child.wait().unwrap();
   |
   = note: `#[warn(unused_must_use)]` on by default
   = note: this ExitStatus might represent an error that should be checked and handled

---


---- [ui] ui/try-wait.rs stdout ----
normalized stderr:
warning: unused `ExitStatus` that must be used
  --> $DIR/try-wait.rs:34:5
   |
LL |     me.wait().unwrap();
   |
   = note: `#[warn(unused_must_use)]` on by default
   = note: this ExitStatus might represent an error that should be checked and handled


warning: 1 warning emitted




The actual stderr differed from the expected stderr.
Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/try-wait/try-wait.stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args try-wait.rs`
error: 1 errors occurred comparing output.
status: exit code: 0
status: exit code: 0
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/try-wait.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zemit-future-incompat-report" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/try-wait/a" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/try-wait/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
warning: unused `ExitStatus` that must be used
   |
   |
LL |     me.wait().unwrap();
   |
   = note: `#[warn(unused_must_use)]` on by default
   = note: this ExitStatus might represent an error that should be checked and handled

---
test result: FAILED. 11214 passed; 2 failed; 87 ignored; 0 measured; 0 filtered out; finished in 132.31s



command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--suite" "ui" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-9/bin/FileCheck" "--nodejs" "/usr/bin/node" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python3" "--lldb-python" "/usr/bin/python3" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "9.0.0" "--llvm-components" "aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils aggressiveinstcombine all all-targets amdgpu amdgpuasmparser amdgpucodegen amdgpudesc amdgpudisassembler amdgpuinfo amdgpuutils analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils asmparser asmprinter avr avrasmparser avrcodegen avrdesc avrdisassembler avrinfo binaryformat bitreader bitstreamreader bitwriter bpf bpfasmparser bpfcodegen bpfdesc bpfdisassembler bpfinfo codegen core coroutines coverage debuginfocodeview debuginfodwarf debuginfogsym debuginfomsf debuginfopdb demangle dlltooldriver engine executionengine fuzzmutate globalisel hexagon hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo instcombine instrumentation interpreter ipo irreader jitlink lanai lanaiasmparser lanaicodegen lanaidesc lanaidisassembler lanaiinfo libdriver lineeditor linker lto mc mca mcdisassembler mcjit mcparser mips mipsasmparser mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430 msp430asmparser msp430codegen msp430desc msp430disassembler msp430info native nativecodegen nvptx nvptxcodegen nvptxdesc nvptxinfo objcarcopts object objectyaml option orcjit passes perfjitevents powerpc powerpcasmparser powerpccodegen powerpcdesc powerpcdisassembler powerpcinfo profiledata remarks riscv riscvasmparser riscvcodegen riscvdesc riscvdisassembler riscvinfo riscvutils runtimedyld scalaropts selectiondag sparc sparcasmparser sparccodegen sparcdesc sparcdisassembler sparcinfo support symbolize systemz systemzasmparser systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen target textapi transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler webassemblyinfo windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info x86utils xcore xcorecodegen xcoredesc xcoredisassembler xcoreinfo xray" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"


failed to run: /checkout/obj/build/bootstrap/debug/bootstrap --stage 2 test --exclude src/tools/tidy
Build completed unsuccessfully in 0:13:53

@ijackson
Copy link
Contributor Author

@rustbot modify labels -S-waiting-on-review +S-waiting-on-author

Looks like I am going to be iterating this through the CI for a little while still...

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 28, 2021
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
If you don't need to call methods on the `Child`, then `status` is
more convenient.  This should be mentioned.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
All these examples called `spawn` and then didn't wait for the child (!)

Fix this by having them call .status() rather than .spawn(), and
assert that the status was success.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
See rust-lang#70186 which makes the point about io handles.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
These three doctests called `.status()` but ignored the result.

Fix this.  In two cases, with an assertion, and in the case where we
are just printing something, by printing the exit status value.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
We are making `ExitStatus` `#[must_use]`.  So we need to explicitly
handle the exit status here.  Handle it the same way as the values
from the repeated calls to `try_wait`.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Simply dropping this is usually a bad idea, for the reasons
extensively discussed in the documentation.

Closes: rust-lang#70186
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
For the same reason as futures.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
For the same reason as `Result` is #[must_use]

Cloess: rust-lang#73127
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
@ijackson
Copy link
Contributor Author

OK, with all those fixes, rust-lang/rust compiles again now....

@rustbot modify labels +S-waiting-on-review -S-waiting-on-author

@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 28, 2021
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 28, 2021
@KodrAus
Copy link
Contributor

KodrAus commented Jan 29, 2021

Thanks for the PR @ijackson! This would be great to clean up, but I think we should tread carefully here, because #[must_use] isn't a silver bullet. Adding it to Command seems like a good idea, because it is pretty useless if you don't actually spawn something from it, but it won't catch cases like this:

let mut cmd = Command::new("proc").args(["-a", "-b"]);

if some_condition {
    cmd.arg("-c");
}

// return here without using the command
// #[must_use] doesn't trigger because we "used" the `Command` to add an extra arg

Before adding #[must_use] to ExitStatus it might be good to look into a nicer API for converting the ExitStatus itself into a Result and working with that:

impl process::ExitStatus {
    pub fn success_or<E>(self, err: E) -> Result<(), E> {
        self.success_or_else(|| err)
    }

    pub fn success_or_else<F, E>(self, err: F) -> Result<(), E>
    where
        F: FnOnce() -> E,
    {
        if self.success() {
            Ok(())
        } else {
            Err(err())
        }
    }
}

So that instead of writing:

let status = Command::new(adb_path)
    .arg("push")
    .arg(&exe_file)
    .arg(&self.config.adb_test_dir)
    .status()
    .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));
if !status.success() {
    panic!("Program failed `{:}`", adb_path);
}

We could write:

Command::new(adb_path)
    .args(&["forward", "tcp:5039", "tcp:5039"])
    .status()
    .and_then(|status| status.success_or_else(|| panic!("Program failed `{:}`", adb_path)))
    .unwrap_or_else(|_| panic!("failed to exec `{:?}`", adb_path));

So it seems like something worth pursuing, but I think there's more we should do to make ExitStatus nicer to work with using standard error handling tools first.

@ijackson
Copy link
Contributor Author

ijackson commented Jan 29, 2021 via email

@KodrAus
Copy link
Contributor

KodrAus commented Jan 30, 2021

@ijackson Are you happy if we close this PR for now and move our design discussion back over to #73131?

I think there are definitely some things we should do to make the whole API nicer to use, and could circle back to considering #[must_use] after working through them.

@ijackson
Copy link
Contributor Author

Sure. Closing this MR for now if fine by me. I will do that.

@LukasKalbertodt
Copy link
Member

I just saw this question on StackOverflow where the asking person would have been saved by the #[must_use] on Command. I was surprised the attribute wasn't already there. So yes, I'm very in favor of that.

ijackson added a commit to ijackson/rust that referenced this pull request May 12, 2021
Closes rust-lang#73125

This is in pursuance of
  Issue rust-lang#73127 Consider adding #[must_use] to std::process::ExitStatus

In
  MR rust-lang#81452 Add #[must_use] to [...] process::ExitStatus
we concluded that the existing arrangements in are too awkward
so adding that #[must_use] is blocked on improving the ergonomics.

I wrote a mini-RFC-style discusion of the approach in
  rust-lang#73125 (comment)

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
bors added a commit to rust-lang-ci/rust that referenced this pull request May 18, 2021
Provide ExitStatusError

Closes rust-lang#73125

In MR rust-lang#81452 "Add #[must_use] to [...] process::ExitStatus" we concluded that the existing arrangements in are too awkward so adding that `#[must_use]` is blocked on improving the ergonomics.

I wrote a mini-RFC-style discusion of the approach in rust-lang#73125 (comment)
@ijackson ijackson deleted the must-use-processes branch August 24, 2021 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants