Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 9cab797

Browse files
committed
Auto merge of rust-lang#2414 - RalfJung:cargo-miri, r=RalfJung
A bit of cargo-miri cleanup
2 parents dac1676 + fb428df commit 9cab797

File tree

1 file changed

+48
-65
lines changed

1 file changed

+48
-65
lines changed

cargo-miri/bin.rs

Lines changed: 48 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct CrateRunEnv {
6060

6161
impl CrateRunEnv {
6262
/// Gather all the information we need.
63-
fn collect(args: env::Args, capture_stdin: bool) -> Self {
63+
fn collect(args: impl Iterator<Item = String>, capture_stdin: bool) -> Self {
6464
let args = args.collect();
6565
let env = env::vars_os().collect();
6666
let current_dir = env::current_dir().unwrap().into_os_string();
@@ -757,7 +757,7 @@ enum RustcPhase {
757757
Rustdoc,
758758
}
759759

760-
fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
760+
fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
761761
/// Determines if we are being invoked (as rustc) to build a crate for
762762
/// the "target" architecture, in contrast to the "host" architecture.
763763
/// Host crates are for build scripts and proc macros and still need to
@@ -978,10 +978,11 @@ enum RunnerPhase {
978978
Rustdoc,
979979
}
980980

981-
fn phase_runner(binary: &Path, binary_args: impl Iterator<Item = String>, phase: RunnerPhase) {
981+
fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: RunnerPhase) {
982982
let verbose = std::env::var("MIRI_VERBOSE")
983983
.map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
984984

985+
let binary = binary_args.next().unwrap();
985986
let file = File::open(&binary)
986987
.unwrap_or_else(|_| show_error(format!("file {:?} not found or `cargo-miri` invoked incorrectly; please only invoke this binary through `cargo miri`", binary)));
987988
let file = BufReader::new(file);
@@ -1007,14 +1008,16 @@ fn phase_runner(binary: &Path, binary_args: impl Iterator<Item = String>, phase:
10071008
// Set missing env vars. We prefer build-time env vars over run-time ones; see
10081009
// <https://github.com/rust-lang/miri/issues/1661> for the kind of issue that fixes.
10091010
for (name, val) in info.env {
1010-
if verbose > 0 {
1011-
if let Some(old_val) = env::var_os(&name) {
1012-
if old_val != val {
1013-
eprintln!(
1014-
"[cargo-miri runner] Overwriting run-time env var {:?}={:?} with build-time value {:?}",
1015-
name, old_val, val
1016-
);
1017-
}
1011+
if let Some(old_val) = env::var_os(&name) {
1012+
if old_val == val {
1013+
// This one did not actually change, no need to re-set it.
1014+
// (This keeps the `debug_cmd` below more manageable.)
1015+
continue;
1016+
} else if verbose > 0 {
1017+
eprintln!(
1018+
"[cargo-miri runner] Overwriting run-time env var {:?}={:?} with build-time value {:?}",
1019+
name, old_val, val
1020+
);
10181021
}
10191022
}
10201023
cmd.env(name, val);
@@ -1071,25 +1074,16 @@ fn phase_runner(binary: &Path, binary_args: impl Iterator<Item = String>, phase:
10711074
}
10721075
}
10731076

1074-
fn phase_rustdoc(fst_arg: &str, mut args: env::Args) {
1077+
fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
10751078
let verbose = std::env::var("MIRI_VERBOSE")
10761079
.map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
10771080

10781081
// phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here;
10791082
// just default to a straight-forward invocation for now:
10801083
let mut cmd = Command::new("rustdoc");
10811084

1082-
// Because of the way the main function is structured, we have to take the first argument spearately
1083-
// from the rest; to simplify the following argument patching loop, we'll just skip that one.
1084-
// This is fine for now, because cargo will never pass --extern arguments in the first position,
1085-
// but we should defensively assert that this will work.
10861085
let extern_flag = "--extern";
1087-
assert!(fst_arg != extern_flag);
1088-
cmd.arg(fst_arg);
1089-
10901086
let runtool_flag = "--runtool";
1091-
// `crossmode` records if *any* argument matches `runtool_flag`; here we check the first one.
1092-
let mut crossmode = fst_arg == runtool_flag;
10931087
while let Some(arg) = args.next() {
10941088
if arg == extern_flag {
10951089
// Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
@@ -1098,17 +1092,12 @@ fn phase_rustdoc(fst_arg: &str, mut args: env::Args) {
10981092
// An existing --runtool flag indicates cargo is running in cross-target mode, which we don't support.
10991093
// Note that this is only passed when cargo is run with the unstable -Zdoctest-xcompile flag;
11001094
// otherwise, we won't be called as rustdoc at all.
1101-
crossmode = true;
1102-
break;
1095+
show_error(format!("cross-interpreting doctests is not currently supported by Miri."));
11031096
} else {
11041097
cmd.arg(arg);
11051098
}
11061099
}
11071100

1108-
if crossmode {
1109-
show_error(format!("cross-interpreting doctests is not currently supported by Miri."));
1110-
}
1111-
11121101
// Doctests of `proc-macro` crates (and their dependencies) are always built for the host,
11131102
// so we are not able to run them in Miri.
11141103
if ArgFlagValueIter::new("--crate-type").any(|crate_type| crate_type == "proc-macro") {
@@ -1178,52 +1167,46 @@ fn main() {
11781167
// since we don't specify any runtool-args, and rustdoc supplies multiple arguments to
11791168
// the test-builder unconditionally, we can just check the number of remaining arguments:
11801169
if args.len() == 1 {
1181-
let arg = args.next().unwrap();
1182-
let binary = Path::new(&arg);
1183-
if binary.exists() {
1184-
phase_runner(binary, args, RunnerPhase::Rustdoc);
1185-
} else {
1186-
show_error(format!(
1187-
"`cargo-miri` called with non-existing path argument `{}` in rustdoc mode; please invoke this binary through `cargo miri`",
1188-
arg
1189-
));
1190-
}
1170+
phase_runner(args, RunnerPhase::Rustdoc);
11911171
} else {
11921172
phase_rustc(args, RustcPhase::Rustdoc);
11931173
}
11941174

11951175
return;
11961176
}
11971177

1198-
match args.next().as_deref() {
1199-
Some("miri") => phase_cargo_miri(args),
1200-
Some(arg) => {
1201-
// If the first arg is equal to the RUSTC variable (which should be set at this point),
1202-
// then we need to behave as rustc. This is the somewhat counter-intuitive behavior of
1203-
// having both RUSTC and RUSTC_WRAPPER set (see
1204-
// https://github.com/rust-lang/cargo/issues/10886).
1205-
if arg == env::var_os("RUSTC").unwrap() {
1206-
return phase_rustc(args, RustcPhase::Build);
1207-
}
1208-
// We have to distinguish the "runner" and "rustdoc" cases.
1209-
// As runner, the first argument is the binary (a file that should exist, with an absolute path);
1210-
// as rustdoc, the first argument is a flag (`--something`).
1211-
let binary = Path::new(arg);
1212-
if binary.exists() {
1213-
assert!(!arg.starts_with("--")); // not a flag
1214-
phase_runner(binary, args, RunnerPhase::Cargo);
1215-
} else if arg.starts_with("--") {
1216-
phase_rustdoc(arg, args);
1217-
} else {
1218-
show_error(format!(
1219-
"`cargo-miri` called with unexpected first argument `{}`; please only invoke this binary through `cargo miri`",
1220-
arg
1221-
));
1222-
}
1178+
let mut args = args.peekable();
1179+
if args.next_if(|a| a == "miri").is_some() {
1180+
phase_cargo_miri(args);
1181+
} else if let Some(arg) = args.peek().cloned() {
1182+
// Cargo calls us for everything it does. We could be invoked as rustc, rustdoc, or the runner.
1183+
1184+
// If the first arg is equal to the RUSTC variable (which should be set at this point),
1185+
// then we need to behave as rustc. This is the somewhat counter-intuitive behavior of
1186+
// having both RUSTC and RUSTC_WRAPPER set (see
1187+
// https://github.com/rust-lang/cargo/issues/10886).
1188+
if arg == env::var("RUSTC").unwrap() {
1189+
args.next().unwrap(); // consume wrapped RUSTC command.
1190+
return phase_rustc(args, RustcPhase::Build);
12231191
}
1224-
_ =>
1192+
// We have to distinguish the "runner" and "rustdoc" cases.
1193+
// As runner, the first argument is the binary (a file that should exist, with an absolute path);
1194+
// as rustdoc, the first argument is a flag (`--something`).
1195+
let binary = Path::new(&arg);
1196+
if binary.exists() {
1197+
assert!(!arg.starts_with("--")); // not a flag
1198+
phase_runner(args, RunnerPhase::Cargo);
1199+
} else if arg.starts_with("--") {
1200+
phase_rustdoc(args);
1201+
} else {
12251202
show_error(format!(
1226-
"`cargo-miri` called without first argument; please only invoke this binary through `cargo miri`"
1227-
)),
1203+
"`cargo-miri` called with unexpected first argument `{}`; please only invoke this binary through `cargo miri`",
1204+
arg
1205+
));
1206+
}
1207+
} else {
1208+
show_error(format!(
1209+
"`cargo-miri` called without first argument; please only invoke this binary through `cargo miri`"
1210+
));
12281211
}
12291212
}

0 commit comments

Comments
 (0)