@@ -60,7 +60,7 @@ struct CrateRunEnv {
6060
6161impl 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