Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ef2e85e

Browse files
committedJun 9, 2024
Auto merge of #126197 - jieyouxu:rmake-must-use, r=<try>
run-make: annotate library with `#[must_use]` and enforce `unused_must_use` in rmake.rs Commits up to 706abf6 are from #125752. This PR adds `#[must_use]` annotations to functions of the `run_make_support` library where it makes sense, and adjusts compiletest to compile rmake.rs with `-Dunused_must_use`. The rationale is that it's highly likely that unused `#[must_use]` values in rmake.rs test files are bugs. For example, unused fs/io results are often crucial to the correctness of the test and often unchecked fs/io results allow the test to silently pass where it would've failed if the result was checked. try-job: test-various try-job: x86_64-msvc
2 parents 212841e + 8d182e3 commit ef2e85e

File tree

27 files changed

+332
-87
lines changed

27 files changed

+332
-87
lines changed
 

‎Cargo.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3452,7 +3452,7 @@ dependencies = [
34523452

34533453
[[package]]
34543454
name = "run_make_support"
3455-
version = "0.0.0"
3455+
version = "0.2.0"
34563456
dependencies = [
34573457
"gimli 0.28.1",
34583458
"object 0.34.0",

‎src/tools/compiletest/src/runtest.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3551,6 +3551,10 @@ impl<'test> TestCx<'test> {
35513551
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
35523552
.env("LLVM_COMPONENTS", &self.config.llvm_components);
35533553

3554+
// In test code we want to be very pedantic about values being silently discarded that are
3555+
// annotated with `#[must_use]`.
3556+
cmd.arg("-Dunused_must_use");
3557+
35543558
if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
35553559
let mut stage0_sysroot = build_root.clone();
35563560
stage0_sysroot.push("stage0-sysroot");
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Changelog
2+
3+
All notable changes to the `run_make_support` library should be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the support
6+
library should adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) even if it's
7+
not intended for public consumption (it's moreso to help internally, to help test writers track
8+
changes to the support library).
9+
10+
This support library will probably never reach 1.0. Please bump the minor version in `Cargo.toml` if
11+
you make any breaking changes or other significant changes, or bump the patch version for bug fixes.
12+
13+
## [0.2.0] - 2024-06-09
14+
15+
### Changed
16+
17+
- Marked many functions with `#[must_use]`, and rmake.rs are now compiled with `-Dmust_use`.
18+
19+
## [0.1.0] - 2024-06-09
20+
21+
### Changed
22+
23+
- Use *drop bombs* to enforce that commands are executed; a command invocation will panic if it is
24+
constructed but never executed. Execution methods `Command::{run, run_fail}` will defuse the drop
25+
bomb.
26+
- Added `Command` helpers that forward to `std::process::Command` counterparts.
27+
28+
### Removed
29+
30+
- The `env_var` method which was incorrectly named and is `env_clear` underneath and is a footgun
31+
from `impl_common_helpers`. For example, removing `TMPDIR` on Unix and `TMP`/`TEMP` breaks
32+
`std::env::temp_dir` and wrecks anything using that, such as rustc's codgen.
33+
- Removed `Deref`/`DerefMut` for `run_make_support::Command` -> `std::process::Command` because it
34+
causes a method chain like `htmldocck().arg().run()` to fail, because `arg()` resolves to
35+
`std::process::Command` which also returns a `&mut std::process::Command`, causing the `run()` to
36+
be not found.
37+
38+
## [0.0.0] - 2024-06-09
39+
40+
Consider this version to contain all changes made to the support library before we started to track
41+
changes in this changelog.
42+
43+
### Added
44+
45+
- Custom command wrappers around `std::process::Command` (`run_make_support::Command`) and custom
46+
wrapper around `std::process::Output` (`CompletedProcess`) to make it more convenient to work with
47+
commands and their output, and help avoid forgetting to check for exit status.
48+
- `Command`: `set_stdin`, `run`, `run_fail`.
49+
- `CompletedProcess`: `std{err,out}_utf8`, `status`, `assert_std{err,out}_{equals, contains,
50+
not_contains}`, `assert_exit_code`.
51+
- `impl_common_helpers` macro to avoid repeating adding common convenience methods, including:
52+
- Environment manipulation methods: `env`, `env_remove`
53+
- Command argument providers: `arg`, `args`
54+
- Common invocation inspection (of the command invocation up until `inspect` is called):
55+
`inspect`
56+
- Execution methods: `run` (for commands expected to succeed execution, exit status `0`) and
57+
`run_fail` (for commands expected to fail execution, exit status non-zero).
58+
- Command wrappers around: `rustc`, `clang`, `cc`, `rustc`, `rustdoc`, `llvm-readobj`.
59+
- Thin helpers to construct `python` and `htmldocck` commands.
60+
- `run` and `run_fail` (like `Command::{run, run_fail}`) for running binaries, which sets suitable
61+
env vars (like `LD_LIB_PATH` or equivalent, `TARGET_RPATH_ENV`, `PATH` on Windows).
62+
- Pseudo command `diff` which has similar functionality as the cli util but not the same API.
63+
- Convenience panic-on-fail helpers `env_var`, `env_var_os`, `cwd` for their `std::env` conterparts.
64+
- Convenience panic-on-fail helpers for reading respective env vars: `target`, `source_root`.
65+
- Platform check helpers: `is_windows`, `is_msvc`, `cygpath_windows`, `uname`.
66+
- fs helpers: `copy_dir_all`.
67+
- `recursive_diff` helper.
68+
- Generic `assert_not_contains` helper.
69+
- Scoped run-with-teardown helper `run_in_tmpdir` which is designed to run commands in a temporary
70+
directory that is cleared when closure returns.
71+
- Helpers for constructing the name of binaries and libraries: `rust_lib_name`, `static_lib_name`,
72+
`bin_name`, `dynamic_lib_name`.
73+
- Re-export libraries: `gimli`, `object`, `regex`, `wasmparsmer`.

‎src/tools/run-make-support/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "run_make_support"
3-
version = "0.0.0"
3+
version = "0.2.0"
44
edition = "2021"
55

66
[dependencies]

‎src/tools/run-make-support/src/cc.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ use crate::{bin_name, cygpath_windows, env_var, is_msvc, is_windows, uname};
77
///
88
/// WARNING: This means that what flags are accepted by the underlying C compiler is
99
/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
10+
#[track_caller]
1011
pub fn cc() -> Cc {
1112
Cc::new()
1213
}
1314

1415
/// A platform-specific C compiler invocation builder. The specific C compiler used is
1516
/// passed down from compiletest.
1617
#[derive(Debug)]
18+
#[must_use]
1719
pub struct Cc {
1820
cmd: Command,
1921
}
@@ -25,6 +27,7 @@ impl Cc {
2527
///
2628
/// WARNING: This means that what flags are accepted by the underlying C compile is
2729
/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
30+
#[track_caller]
2831
pub fn new() -> Self {
2932
let compiler = env_var("CC");
3033

@@ -84,11 +87,6 @@ impl Cc {
8487
self.cmd.arg(path.as_ref());
8588
self
8689
}
87-
88-
/// Get the [`Output`][::std::process::Output] of the finished process.
89-
pub fn command_output(&mut self) -> ::std::process::Output {
90-
self.cmd.output().expect("failed to get output of finished process")
91-
}
9290
}
9391

9492
/// `EXTRACFLAGS`

‎src/tools/run-make-support/src/clang.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ use crate::command::Command;
44
use crate::{bin_name, env_var};
55

66
/// Construct a new `clang` invocation. `clang` is not always available for all targets.
7+
#[track_caller]
78
pub fn clang() -> Clang {
89
Clang::new()
910
}
1011

1112
/// A `clang` invocation builder.
1213
#[derive(Debug)]
14+
#[must_use]
1315
pub struct Clang {
1416
cmd: Command,
1517
}
@@ -18,6 +20,7 @@ crate::impl_common_helpers!(Clang);
1820

1921
impl Clang {
2022
/// Construct a new `clang` invocation. `clang` is not always available for all targets.
23+
#[track_caller]
2124
pub fn new() -> Self {
2225
let clang = env_var("CLANG");
2326
let cmd = Command::new(clang);

‎src/tools/run-make-support/src/command.rs

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,125 @@
1-
use crate::{assert_not_contains, handle_failed_output};
1+
use std::ffi;
22
use std::ffi::OsStr;
33
use std::io::Write;
4-
use std::ops::{Deref, DerefMut};
4+
use std::panic;
5+
use std::path::Path;
56
use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
67

7-
/// This is a custom command wrapper that simplifies working with commands
8-
/// and makes it easier to ensure that we check the exit status of executed
9-
/// processes.
8+
use crate::drop_bomb::DropBomb;
9+
use crate::{assert_not_contains, handle_failed_output};
10+
11+
/// This is a custom command wrapper that simplifies working with commands and makes it easier to
12+
/// ensure that we check the exit status of executed processes.
13+
///
14+
/// # A [`Command`] must be executed
15+
///
16+
/// A [`Command`] is armed by a [`DropBomb`] on construction to enforce that it will be executed. If
17+
/// a [`Commmand`] is constructed but never executed, the drop bomb will explode and cause the test
18+
/// to panic. Execution methods [`run`] and [`run_fail`] will defuse the drop bomb. A test
19+
/// containing constructed but never executed commands is dangerous because it can give a false
20+
/// sense of confidence.
21+
///
22+
/// [`run`]: Self::run
23+
/// [`run_fail`]: Self::run
1024
#[derive(Debug)]
1125
pub struct Command {
1226
cmd: StdCommand,
1327
stdin: Option<Box<[u8]>>,
28+
drop_bomb: DropBomb,
1429
}
1530

1631
impl Command {
17-
pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
18-
Self { cmd: StdCommand::new(program), stdin: None }
32+
#[track_caller]
33+
pub fn new<P: AsRef<OsStr>>(program: P) -> Self {
34+
let program = program.as_ref();
35+
Self { cmd: StdCommand::new(program), stdin: None, drop_bomb: DropBomb::arm(program) }
1936
}
2037

2138
pub fn set_stdin(&mut self, stdin: Box<[u8]>) {
2239
self.stdin = Some(stdin);
2340
}
2441

42+
/// Specify an environment variable.
43+
pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
44+
where
45+
K: AsRef<ffi::OsStr>,
46+
V: AsRef<ffi::OsStr>,
47+
{
48+
self.cmd.env(key, value);
49+
self
50+
}
51+
52+
/// Remove an environmental variable.
53+
pub fn env_remove<K>(&mut self, key: K) -> &mut Self
54+
where
55+
K: AsRef<ffi::OsStr>,
56+
{
57+
self.cmd.env_remove(key);
58+
self
59+
}
60+
61+
/// Generic command argument provider. Prefer specific helper methods if possible.
62+
/// Note that for some executables, arguments might be platform specific. For C/C++
63+
/// compilers, arguments might be platform *and* compiler specific.
64+
pub fn arg<S>(&mut self, arg: S) -> &mut Self
65+
where
66+
S: AsRef<ffi::OsStr>,
67+
{
68+
self.cmd.arg(arg);
69+
self
70+
}
71+
72+
/// Generic command arguments provider. Prefer specific helper methods if possible.
73+
/// Note that for some executables, arguments might be platform specific. For C/C++
74+
/// compilers, arguments might be platform *and* compiler specific.
75+
pub fn args<S>(&mut self, args: &[S]) -> &mut Self
76+
where
77+
S: AsRef<ffi::OsStr>,
78+
{
79+
self.cmd.args(args);
80+
self
81+
}
82+
83+
/// Inspect what the underlying [`std::process::Command`] is up to the
84+
/// current construction.
85+
pub fn inspect<I>(&mut self, inspector: I) -> &mut Self
86+
where
87+
I: FnOnce(&StdCommand),
88+
{
89+
inspector(&self.cmd);
90+
self
91+
}
92+
93+
/// Set the path where the command will be run.
94+
pub fn current_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
95+
self.cmd.current_dir(path);
96+
self
97+
}
98+
2599
/// Run the constructed command and assert that it is successfully run.
26100
#[track_caller]
27101
pub fn run(&mut self) -> CompletedProcess {
28-
let caller_location = std::panic::Location::caller();
29-
let caller_line_number = caller_location.line();
30-
102+
self.drop_bomb.defuse();
31103
let output = self.command_output();
32104
if !output.status().success() {
33-
handle_failed_output(&self, output, caller_line_number);
105+
handle_failed_output(&self, output, panic::Location::caller().line());
34106
}
35107
output
36108
}
37109

38110
/// Run the constructed command and assert that it does not successfully run.
39111
#[track_caller]
40112
pub fn run_fail(&mut self) -> CompletedProcess {
41-
let caller_location = std::panic::Location::caller();
42-
let caller_line_number = caller_location.line();
43-
113+
self.drop_bomb.defuse();
44114
let output = self.command_output();
45115
if output.status().success() {
46-
handle_failed_output(&self, output, caller_line_number);
116+
handle_failed_output(&self, output, panic::Location::caller().line());
47117
}
48118
output
49119
}
50120

51121
#[track_caller]
52-
pub(crate) fn command_output(&mut self) -> CompletedProcess {
122+
fn command_output(&mut self) -> CompletedProcess {
53123
// let's make sure we piped all the input and outputs
54124
self.cmd.stdin(Stdio::piped());
55125
self.cmd.stdout(Stdio::piped());
@@ -71,20 +141,6 @@ impl Command {
71141
}
72142
}
73143

74-
impl Deref for Command {
75-
type Target = StdCommand;
76-
77-
fn deref(&self) -> &Self::Target {
78-
&self.cmd
79-
}
80-
}
81-
82-
impl DerefMut for Command {
83-
fn deref_mut(&mut self) -> &mut Self::Target {
84-
&mut self.cmd
85-
}
86-
}
87-
88144
/// Represents the result of an executed process.
89145
/// The various `assert_` helper methods should preferably be used for
90146
/// checking the contents of stdout/stderr.
@@ -93,14 +149,17 @@ pub struct CompletedProcess {
93149
}
94150

95151
impl CompletedProcess {
152+
#[must_use]
96153
pub fn stdout_utf8(&self) -> String {
97154
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
98155
}
99156

157+
#[must_use]
100158
pub fn stderr_utf8(&self) -> String {
101159
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
102160
}
103161

162+
#[must_use]
104163
pub fn status(&self) -> ExitStatus {
105164
self.output.status
106165
}

‎src/tools/run-make-support/src/diff/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,38 @@ use regex::Regex;
22
use similar::TextDiff;
33
use std::path::Path;
44

5+
use crate::drop_bomb::DropBomb;
6+
57
#[cfg(test)]
68
mod tests;
79

10+
#[track_caller]
811
pub fn diff() -> Diff {
912
Diff::new()
1013
}
1114

1215
#[derive(Debug)]
16+
#[must_use]
1317
pub struct Diff {
1418
expected: Option<String>,
1519
expected_name: Option<String>,
1620
actual: Option<String>,
1721
actual_name: Option<String>,
1822
normalizers: Vec<(String, String)>,
23+
drop_bomb: DropBomb,
1924
}
2025

2126
impl Diff {
2227
/// Construct a bare `diff` invocation.
28+
#[track_caller]
2329
pub fn new() -> Self {
2430
Self {
2531
expected: None,
2632
expected_name: None,
2733
actual: None,
2834
actual_name: None,
2935
normalizers: Vec::new(),
36+
drop_bomb: DropBomb::arm("diff"),
3037
}
3138
}
3239

@@ -79,9 +86,9 @@ impl Diff {
7986
self
8087
}
8188

82-
/// Executes the diff process, prints any differences to the standard error.
8389
#[track_caller]
84-
pub fn run(&self) {
90+
pub fn run(&mut self) {
91+
self.drop_bomb.defuse();
8592
let expected = self.expected.as_ref().expect("expected text not set");
8693
let mut actual = self.actual.as_ref().expect("actual text not set").to_string();
8794
let expected_name = self.expected_name.as_ref().unwrap();
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//! This module implements "drop bombs" intended for use by command wrappers to ensure that the
2+
//! constructed commands are *eventually* executed. This is exactly like `rustc_errors::Diag` where
3+
//! we force every `Diag` to be consumed or we emit a bug, but we panic instead.
4+
//!
5+
//! This is adapted from <https://docs.rs/drop_bomb/latest/drop_bomb/> and simplified for our
6+
//! purposes.
7+
8+
use std::ffi::{OsStr, OsString};
9+
use std::panic;
10+
11+
#[cfg(test)]
12+
mod tests;
13+
14+
#[derive(Debug)]
15+
pub(crate) struct DropBomb {
16+
command: OsString,
17+
defused: bool,
18+
armed_line: u32,
19+
}
20+
21+
impl DropBomb {
22+
/// Arm a [`DropBomb`]. If the value is dropped without being [`defused`][Self::defused], then
23+
/// it will panic. It is expected that the command wrapper uses `#[track_caller]` to help
24+
/// propagate the caller info from rmake.rs.
25+
#[track_caller]
26+
pub(crate) fn arm<S: AsRef<OsStr>>(command: S) -> DropBomb {
27+
DropBomb {
28+
command: command.as_ref().into(),
29+
defused: false,
30+
armed_line: panic::Location::caller().line(),
31+
}
32+
}
33+
34+
/// Defuse the [`DropBomb`]. This will prevent the drop bomb from panicking when dropped.
35+
pub(crate) fn defuse(&mut self) {
36+
self.defused = true;
37+
}
38+
}
39+
40+
impl Drop for DropBomb {
41+
fn drop(&mut self) {
42+
if !self.defused && !std::thread::panicking() {
43+
panic!(
44+
"command constructed but not executed at line {}: `{}`",
45+
self.armed_line,
46+
self.command.to_string_lossy()
47+
)
48+
}
49+
}
50+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::DropBomb;
2+
3+
#[test]
4+
#[should_panic]
5+
fn test_arm() {
6+
let bomb = DropBomb::arm("hi :3");
7+
drop(bomb); // <- armed bomb should explode when not defused
8+
}
9+
10+
#[test]
11+
fn test_defuse() {
12+
let mut bomb = DropBomb::arm("hi :3");
13+
bomb.defuse();
14+
drop(bomb); // <- defused bomb should not explode
15+
}

‎src/tools/run-make-support/src/lib.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod cc;
77
pub mod clang;
88
mod command;
99
pub mod diff;
10+
mod drop_bomb;
1011
pub mod llvm_readobj;
1112
pub mod run;
1213
pub mod rustc;
@@ -16,6 +17,7 @@ use std::env;
1617
use std::ffi::OsString;
1718
use std::fs;
1819
use std::io;
20+
use std::panic;
1921
use std::path::{Path, PathBuf};
2022

2123
pub use gimli;
@@ -31,13 +33,17 @@ pub use run::{cmd, run, run_fail};
3133
pub use rustc::{aux_build, rustc, Rustc};
3234
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
3335

36+
#[track_caller]
37+
#[must_use]
3438
pub fn env_var(name: &str) -> String {
3539
match env::var(name) {
3640
Ok(v) => v,
3741
Err(err) => panic!("failed to retrieve environment variable {name:?}: {err:?}"),
3842
}
3943
}
4044

45+
#[track_caller]
46+
#[must_use]
4147
pub fn env_var_os(name: &str) -> OsString {
4248
match env::var_os(name) {
4349
Some(v) => v,
@@ -46,42 +52,52 @@ pub fn env_var_os(name: &str) -> OsString {
4652
}
4753

4854
/// `TARGET`
55+
#[must_use]
4956
pub fn target() -> String {
5057
env_var("TARGET")
5158
}
5259

5360
/// Check if target is windows-like.
61+
#[must_use]
5462
pub fn is_windows() -> bool {
5563
target().contains("windows")
5664
}
5765

5866
/// Check if target uses msvc.
67+
#[must_use]
5968
pub fn is_msvc() -> bool {
6069
target().contains("msvc")
6170
}
6271

6372
/// Check if target uses macOS.
73+
#[must_use]
6474
pub fn is_darwin() -> bool {
6575
target().contains("darwin")
6676
}
6777

78+
#[track_caller]
79+
#[must_use]
6880
pub fn python_command() -> Command {
6981
let python_path = env_var("PYTHON");
7082
Command::new(python_path)
7183
}
7284

85+
#[track_caller]
86+
#[must_use]
7387
pub fn htmldocck() -> Command {
7488
let mut python = python_command();
7589
python.arg(source_root().join("src/etc/htmldocck.py"));
7690
python
7791
}
7892

7993
/// Path to the root rust-lang/rust source checkout.
94+
#[must_use]
8095
pub fn source_root() -> PathBuf {
8196
env_var("SOURCE_ROOT").into()
8297
}
8398

8499
/// Construct the static library name based on the platform.
100+
#[must_use]
85101
pub fn static_lib_name(name: &str) -> String {
86102
// See tools.mk (irrelevant lines omitted):
87103
//
@@ -106,6 +122,7 @@ pub fn static_lib_name(name: &str) -> String {
106122
}
107123

108124
/// Construct the dynamic library name based on the platform.
125+
#[must_use]
109126
pub fn dynamic_lib_name(name: &str) -> String {
110127
// See tools.mk (irrelevant lines omitted):
111128
//
@@ -132,6 +149,7 @@ pub fn dynamic_lib_name(name: &str) -> String {
132149
}
133150
}
134151

152+
#[must_use]
135153
pub fn dynamic_lib_extension() -> &'static str {
136154
if is_darwin() {
137155
"dylib"
@@ -143,48 +161,49 @@ pub fn dynamic_lib_extension() -> &'static str {
143161
}
144162

145163
/// Construct a rust library (rlib) name.
164+
#[must_use]
146165
pub fn rust_lib_name(name: &str) -> String {
147166
format!("lib{name}.rlib")
148167
}
149168

150169
/// Construct the binary name based on platform.
170+
#[must_use]
151171
pub fn bin_name(name: &str) -> String {
152172
if is_windows() { format!("{name}.exe") } else { name.to_string() }
153173
}
154174

155175
/// Return the current working directory.
176+
#[must_use]
156177
pub fn cwd() -> PathBuf {
157178
env::current_dir().unwrap()
158179
}
159180

160181
/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
161182
/// available on the platform!
162183
#[track_caller]
184+
#[must_use]
163185
pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
164-
let caller_location = std::panic::Location::caller();
165-
let caller_line_number = caller_location.line();
166-
186+
let caller = panic::Location::caller();
167187
let mut cygpath = Command::new("cygpath");
168188
cygpath.arg("-w");
169189
cygpath.arg(path.as_ref());
170-
let output = cygpath.command_output();
190+
let output = cygpath.run();
171191
if !output.status().success() {
172-
handle_failed_output(&cygpath, output, caller_line_number);
192+
handle_failed_output(&cygpath, output, caller.line());
173193
}
174194
// cygpath -w can attach a newline
175195
output.stdout_utf8().trim().to_string()
176196
}
177197

178198
/// Run `uname`. This assumes that `uname` is available on the platform!
179199
#[track_caller]
200+
#[must_use]
180201
pub fn uname() -> String {
181-
let caller_location = std::panic::Location::caller();
182-
let caller_line_number = caller_location.line();
183-
202+
let caller = panic::Location::caller();
184203
let mut uname = Command::new("uname");
185-
let output = uname.command_output();
204+
let output = uname.run();
186205
if !output.status().success() {
187-
handle_failed_output(&uname, output, caller_line_number);
206+
handle_failed_output(&uname, output, caller.line());
188207
}
189208
output.stdout_utf8()
190209
}
@@ -372,12 +391,6 @@ macro_rules! impl_common_helpers {
372391
self
373392
}
374393

375-
/// Clear all environmental variables.
376-
pub fn env_var(&mut self) -> &mut Self {
377-
self.cmd.env_clear();
378-
self
379-
}
380-
381394
/// Generic command argument provider. Prefer specific helper methods if possible.
382395
/// Note that for some executables, arguments might be platform specific. For C/C++
383396
/// compilers, arguments might be platform *and* compiler specific.
@@ -406,7 +419,7 @@ macro_rules! impl_common_helpers {
406419
where
407420
I: FnOnce(&::std::process::Command),
408421
{
409-
inspector(&self.cmd);
422+
self.cmd.inspect(inspector);
410423
self
411424
}
412425

@@ -423,7 +436,7 @@ macro_rules! impl_common_helpers {
423436
}
424437

425438
/// Set the path where the command will be run.
426-
pub fn current_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
439+
pub fn current_dir<P: AsRef<::std::path::Path>>(&mut self, path: P) -> &mut Self {
427440
self.cmd.current_dir(path);
428441
self
429442
}

‎src/tools/run-make-support/src/llvm_readobj.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ use crate::env_var;
55

66
/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
77
/// at `$LLVM_BIN_DIR/llvm-readobj`.
8+
#[track_caller]
89
pub fn llvm_readobj() -> LlvmReadobj {
910
LlvmReadobj::new()
1011
}
1112

1213
/// A `llvm-readobj` invocation builder.
1314
#[derive(Debug)]
15+
#[must_use]
1416
pub struct LlvmReadobj {
1517
cmd: Command,
1618
}
@@ -20,6 +22,7 @@ crate::impl_common_helpers!(LlvmReadobj);
2022
impl LlvmReadobj {
2123
/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
2224
/// at `$LLVM_BIN_DIR/llvm-readobj`.
25+
#[track_caller]
2326
pub fn new() -> Self {
2427
let llvm_bin_dir = env_var("LLVM_BIN_DIR");
2528
let llvm_bin_dir = PathBuf::from(llvm_bin_dir);

‎src/tools/run-make-support/src/run.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use std::env;
22
use std::ffi::OsStr;
3+
use std::panic;
34
use std::path::{Path, PathBuf};
45

56
use crate::command::{Command, CompletedProcess};
67
use crate::{cwd, env_var, is_windows, set_host_rpath};
78

89
use super::handle_failed_output;
910

10-
fn run_common(name: &str) -> (Command, CompletedProcess) {
11+
#[track_caller]
12+
fn run_common(name: &str) -> Command {
1113
let mut bin_path = PathBuf::new();
1214
bin_path.push(cwd());
1315
bin_path.push(name);
@@ -34,38 +36,36 @@ fn run_common(name: &str) -> (Command, CompletedProcess) {
3436
cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
3537
}
3638

37-
let output = cmd.command_output();
38-
(cmd, output)
39+
cmd
3940
}
4041

4142
/// Run a built binary and make sure it succeeds.
4243
#[track_caller]
4344
pub fn run(name: &str) -> CompletedProcess {
44-
let caller_location = std::panic::Location::caller();
45-
let caller_line_number = caller_location.line();
46-
47-
let (cmd, output) = run_common(name);
45+
let caller = panic::Location::caller();
46+
let mut cmd = run_common(name);
47+
let output = cmd.run();
4848
if !output.status().success() {
49-
handle_failed_output(&cmd, output, caller_line_number);
49+
handle_failed_output(&cmd, output, caller.line());
5050
}
5151
output
5252
}
5353

5454
/// Run a built binary and make sure it fails.
5555
#[track_caller]
5656
pub fn run_fail(name: &str) -> CompletedProcess {
57-
let caller_location = std::panic::Location::caller();
58-
let caller_line_number = caller_location.line();
59-
60-
let (cmd, output) = run_common(name);
57+
let caller = panic::Location::caller();
58+
let mut cmd = run_common(name);
59+
let output = cmd.run_fail();
6160
if output.status().success() {
62-
handle_failed_output(&cmd, output, caller_line_number);
61+
handle_failed_output(&cmd, output, caller.line());
6362
}
6463
output
6564
}
6665

67-
/// Create a new custom Command.
68-
/// This should be preferred to creating `std::process::Command` directly.
66+
/// Create a new custom [`Command`]. This should be preferred to creating [`std::process::Command`]
67+
/// directly.
68+
#[track_caller]
6969
pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command {
7070
let mut command = Command::new(program);
7171
set_host_rpath(&mut command);

‎src/tools/run-make-support/src/rustc.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,27 @@ use std::path::Path;
55
use crate::{command, cwd, env_var, set_host_rpath};
66

77
/// Construct a new `rustc` invocation.
8+
#[track_caller]
89
pub fn rustc() -> Rustc {
910
Rustc::new()
1011
}
1112

1213
/// Construct a new `rustc` aux-build invocation.
14+
#[track_caller]
1315
pub fn aux_build() -> Rustc {
1416
Rustc::new_aux_build()
1517
}
1618

1719
/// A `rustc` invocation builder.
1820
#[derive(Debug)]
21+
#[must_use]
1922
pub struct Rustc {
2023
cmd: Command,
2124
}
2225

2326
crate::impl_common_helpers!(Rustc);
2427

28+
#[track_caller]
2529
fn setup_common() -> Command {
2630
let rustc = env_var("RUSTC");
2731
let mut cmd = Command::new(rustc);
@@ -34,12 +38,14 @@ impl Rustc {
3438
// `rustc` invocation constructor methods
3539

3640
/// Construct a new `rustc` invocation.
41+
#[track_caller]
3742
pub fn new() -> Self {
3843
let cmd = setup_common();
3944
Self { cmd }
4045
}
4146

4247
/// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
48+
#[track_caller]
4349
pub fn new_aux_build() -> Self {
4450
let mut cmd = setup_common();
4551
cmd.arg("--crate-type=lib");

‎src/tools/run-make-support/src/rustdoc.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@ pub fn bare_rustdoc() -> Rustdoc {
1010
}
1111

1212
/// Construct a new `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
13+
#[track_caller]
1314
pub fn rustdoc() -> Rustdoc {
1415
Rustdoc::new()
1516
}
1617

1718
#[derive(Debug)]
19+
#[must_use]
1820
pub struct Rustdoc {
1921
cmd: Command,
2022
}
2123

2224
crate::impl_common_helpers!(Rustdoc);
2325

26+
#[track_caller]
2427
fn setup_common() -> Command {
2528
let rustdoc = env_var("RUSTDOC");
2629
let mut cmd = Command::new(rustdoc);
@@ -30,12 +33,14 @@ fn setup_common() -> Command {
3033

3134
impl Rustdoc {
3235
/// Construct a bare `rustdoc` invocation.
36+
#[track_caller]
3337
pub fn bare() -> Self {
3438
let cmd = setup_common();
3539
Self { cmd }
3640
}
3741

3842
/// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
43+
#[track_caller]
3944
pub fn new() -> Self {
4045
let mut cmd = setup_common();
4146
let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");

‎tests/run-make/c-link-to-rust-staticlib/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ fn main() {
1010
rustc().input("foo.rs").run();
1111
cc().input("bar.c").input(static_lib_name("foo")).out_exe("bar").args(&extra_c_flags()).run();
1212
run("bar");
13-
fs::remove_file(static_lib_name("foo"));
13+
fs::remove_file(static_lib_name("foo")).unwrap();
1414
run("bar");
1515
}

‎tests/run-make/compiler-builtins/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn main() {
3535
let rustc = env_var("RUSTC");
3636
let bootstrap_cargo = env_var("BOOTSTRAP_CARGO");
3737
let mut cmd = cmd(bootstrap_cargo);
38-
cmd.args([
38+
cmd.args(&[
3939
"build",
4040
"--manifest-path",
4141
manifest_path.to_str().unwrap(),

‎tests/run-make/doctests-keep-binaries/rmake.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) {
1010
create_dir(&out_dir).expect("failed to create doctests folder");
1111
rustc().input("t.rs").crate_type("rlib").run();
1212
callback(&out_dir, Path::new("libt.rlib"));
13-
remove_dir_all(out_dir);
13+
remove_dir_all(out_dir).unwrap();
1414
}
1515

1616
fn check_generated_binaries() {
@@ -58,6 +58,6 @@ fn main() {
5858
.extern_("t", "libt.rlib")
5959
.run();
6060

61-
remove_dir_all(run_dir_path);
61+
remove_dir_all(run_dir_path).unwrap();
6262
});
6363
}

‎tests/run-make/doctests-runtool/rmake.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ fn main() {
3131
.extern_("t", "libt.rlib")
3232
.run();
3333

34-
remove_dir_all(run_dir);
35-
remove_dir_all(run_tool);
34+
remove_dir_all(run_dir).unwrap();
35+
remove_dir_all(run_tool).unwrap();
3636
}

‎tests/run-make/reset-codegen-1/rmake.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,20 @@ fn main() {
2828
("link-output", Some("link")),
2929
("obj-output", Some("obj")),
3030
("dep-output", Some("dep-info")),
31-
("multi-output", Some("asm,obj")),
3231
];
3332
for (output_file, emit) in flags {
3433
fs::remove_file(output_file).unwrap_or_default();
3534
compile(output_file, emit);
36-
fs::remove_file(output_file);
35+
eprintln!("{output_file}");
36+
fs::remove_file(output_file).unwrap();
37+
}
38+
39+
{
40+
// multi-output has two output artifacts with extensions.
41+
fs::remove_file("multi-output.s").unwrap_or_default();
42+
fs::remove_file("multi-output.o").unwrap_or_default();
43+
compile("multi-output", Some("asm,obj"));
44+
fs::remove_file("multi-output.s").unwrap();
45+
fs::remove_file("multi-output.o").unwrap();
3746
}
3847
}

‎tests/run-make/rustdoc-map-file/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ fn main() {
99
.output(&out_dir)
1010
.run();
1111
// FIXME (GuillaumeGomez): Port the python script to Rust as well.
12-
assert!(python_command().arg("validate_json.py").arg(&out_dir).status().unwrap().success());
12+
python_command().arg("validate_json.py").arg(&out_dir).run();
1313
}

‎tests/run-make/rustdoc-scrape-examples-macros/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ fn main() {
5656
.arg(&ex_dir)
5757
.run();
5858

59-
assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
59+
htmldocck().arg(out_dir).arg("src/lib.rs").run();
6060
}

‎tests/run-make/rustdoc-scrape-examples-remap/scrape.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,5 @@ pub fn scrape(extra_args: &[&str]) {
4545
}
4646
rustdoc.run();
4747

48-
assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
48+
htmldocck().arg(out_dir).arg("src/lib.rs").run();
4949
}

‎tests/run-make/rustdoc-themes/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ fn main() {
2828
std::fs::write(&test_css, test_content).unwrap();
2929

3030
rustdoc().output(&out_dir).input("foo.rs").arg("--theme").arg(&test_css).run();
31-
assert!(htmldocck().arg(out_dir).arg("foo.rs").status().unwrap().success());
31+
htmldocck().arg(out_dir).arg("foo.rs").run();
3232
}

‎tests/run-make/rustdoc-with-out-dir-option/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ use run_make_support::{htmldocck, rustdoc};
33
fn main() {
44
let out_dir = "rustdoc";
55
rustdoc().input("src/lib.rs").crate_name("foobar").crate_type("lib").output(&out_dir).run();
6-
assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
6+
htmldocck().arg(out_dir).arg("src/lib.rs").run();
77
}

‎tests/run-make/rustdoc-with-output-option/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ fn main() {
1212
.arg(&out_dir)
1313
.run();
1414

15-
assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
15+
htmldocck().arg(out_dir).arg("src/lib.rs").run();
1616
}

‎tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ fn main() {
1212
.arg(&out_dir)
1313
.run();
1414

15-
assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
15+
htmldocck().arg(out_dir).arg("src/lib.rs").run();
1616
}

0 commit comments

Comments
 (0)
Please sign in to comment.