diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index fa2a530d9db6..245832245d1f 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -348,11 +348,7 @@ impl StepDescription { eprintln!( "note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" ); - #[cfg(not(test))] - std::process::exit(1); - #[cfg(test)] - // so we can use #[should_panic] - panic!() + crate::detail_exit(1); } } } @@ -1001,7 +997,7 @@ impl<'a> Builder<'a> { if !help_on_error.is_empty() { eprintln!("{}", help_on_error); } - std::process::exit(1); + crate::detail_exit(1); } } @@ -1430,7 +1426,7 @@ impl<'a> Builder<'a> { "error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" ); eprintln!("help: try `rustup component add clippy`"); - std::process::exit(1); + crate::detail_exit(1); }); if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") { rustflags.arg("--cfg=bootstrap"); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b4807d1ab3af..d50950888db9 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -13,7 +13,7 @@ use std::fs; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; -use std::process::{exit, Command, Stdio}; +use std::process::{Command, Stdio}; use std::str; use serde::Deserialize; @@ -1328,7 +1328,7 @@ pub fn run_cargo( }); if !ok { - exit(1); + crate::detail_exit(1); } // Ok now we need to actually find all the files listed in `toplevel`. We've diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 2fc18c9e79e3..e71fbff14dd1 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -11,7 +11,7 @@ use std::ffi::OsStr; use std::fmt; use std::fs; use std::path::{Path, PathBuf}; -use std::process::{exit, Command}; +use std::process::Command; use std::str::FromStr; use crate::builder::{Builder, TaskPath}; @@ -805,8 +805,6 @@ impl Config { let get_toml = |_| TomlConfig::default(); #[cfg(not(test))] let get_toml = |file: &Path| { - use std::process; - let contents = t!(fs::read_to_string(file), format!("config file {} not found", file.display())); // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of @@ -817,7 +815,7 @@ impl Config { Ok(table) => table, Err(err) => { eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err); - process::exit(2); + crate::detail_exit(2); } } }; @@ -1487,7 +1485,7 @@ fn download_ci_rustc_commit( println!("help: maybe your repository history is too shallow?"); println!("help: consider disabling `download-rustc`"); println!("help: or fetch enough history to include one upstream commit"); - exit(1); + crate::detail_exit(1); } // Warn if there were changes to the compiler or standard library since the ancestor commit. diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 7ebae55efc16..eec19ab4fc90 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -4,7 +4,6 @@ //! has various flags to configure how it's run. use std::path::PathBuf; -use std::process; use getopts::Options; @@ -261,7 +260,7 @@ To learn more about a subcommand, run `./x.py -h`", // subcommand. println!("{}\n", subcommand_help); let exit_code = if args.is_empty() { 0 } else { 1 }; - process::exit(exit_code); + crate::detail_exit(exit_code); } }; @@ -347,7 +346,7 @@ To learn more about a subcommand, run `./x.py -h`", } else if verbose { panic!("No paths available for subcommand `{}`", subcommand.as_str()); } - process::exit(exit_code); + crate::detail_exit(exit_code); }; // Done specifying what options are possible, so do the getopts parsing @@ -379,7 +378,7 @@ To learn more about a subcommand, run `./x.py -h`", "Sorry, I couldn't figure out which subcommand you were trying to specify.\n\ You may need to move some options to after the subcommand.\n" ); - process::exit(1); + crate::detail_exit(1); } // Extra help text for some commands match subcommand { @@ -600,7 +599,7 @@ Arguments: eprintln!("error: {}", err); eprintln!("help: the available profiles are:"); eprint!("{}", Profile::all_for_help("- ")); - std::process::exit(1); + crate::detail_exit(1); }) } else { t!(crate::setup::interactive_path()) @@ -614,7 +613,7 @@ Arguments: || matches.opt_str("keep-stage-std").is_some() { eprintln!("--keep-stage not yet supported for x.py check"); - process::exit(1); + crate::detail_exit(1); } } @@ -805,7 +804,7 @@ fn parse_deny_warnings(matches: &getopts::Matches) -> Option { Some("warn") => Some(false), Some(value) => { eprintln!(r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value,); - process::exit(1); + crate::detail_exit(1); } None => None, } diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 60a53c28686b..f25977c1d463 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -32,7 +32,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F code, run `./x.py fmt` instead.", cmd_debug, ); - std::process::exit(1); + crate::detail_exit(1); } } } @@ -114,7 +114,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { eprintln!("./x.py fmt is not supported on this channel"); - std::process::exit(1); + crate::detail_exit(1); }); assert!(rustfmt_path.exists(), "{}", rustfmt_path.display()); let src = build.src.clone(); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 73bd588472df..82025efcbe0e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -109,7 +109,7 @@ use std::env; use std::fs::{self, File}; use std::io; use std::path::{Path, PathBuf}; -use std::process::{self, Command}; +use std::process::Command; use std::str; use filetime::FileTime; @@ -711,7 +711,7 @@ impl Build { for failure in failures.iter() { eprintln!(" - {}\n", failure); } - process::exit(1); + detail_exit(1); } #[cfg(feature = "build-metrics")] @@ -1617,7 +1617,7 @@ Alternatively, set `download-ci-llvm = true` in that `[llvm]` section to download LLVM rather than building it. " ); - std::process::exit(1); + detail_exit(1); } } @@ -1646,6 +1646,20 @@ fn chmod(path: &Path, perms: u32) { #[cfg(windows)] fn chmod(_path: &Path, _perms: u32) {} +/// If code is not 0 (successful exit status), exit status is 101 (rust's default error code.) +/// If the test is running and code is an error code, it will cause a panic. +fn detail_exit(code: i32) -> ! { + // Successful exit + if code == 0 { + std::process::exit(0); + } + if cfg!(test) { + panic!("status code: {}", code); + } else { + std::panic::resume_unwind(Box::new(code)); + } +} + impl Compiler { pub fn with_stage(mut self, stage: u32) -> Compiler { self.stage = stage; diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 64c5dd7aea72..cae41286f087 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -104,7 +104,7 @@ You should install cmake, or set `download-ci-llvm = true` in the than building it. " ); - std::process::exit(1); + crate::detail_exit(1); } } diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 82f55440ce50..740c12ed725e 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -94,7 +94,7 @@ pub fn setup(config: &Config, profile: Profile) { "note: this will use the configuration in {}", profile.include_path(&config.src).display() ); - std::process::exit(1); + crate::detail_exit(1); } let settings = format!( @@ -287,7 +287,7 @@ pub fn interactive_path() -> io::Result { io::stdin().read_line(&mut input)?; if input.is_empty() { eprintln!("EOF on stdin, when expecting answer to question. Giving up."); - std::process::exit(1); + crate::detail_exit(1); } break match parse_with_abbrev(&input) { Ok(profile) => profile, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index f3395507bb08..e4909d64b98c 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -673,7 +673,7 @@ impl Step for Clippy { } if !builder.config.cmd.bless() { - std::process::exit(1); + crate::detail_exit(1); } let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run"); @@ -1021,7 +1021,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` PATH = inferred_rustfmt_dir.display(), CHAN = builder.config.channel, ); - std::process::exit(1); + crate::detail_exit(1); } crate::format::format(&builder, !builder.config.cmd.bless(), &[]); } @@ -1251,7 +1251,7 @@ help: to test the compiler, use `--stage 1` instead help: to test the standard library, use `--stage 0 library/std` instead note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." ); - std::process::exit(1); + crate::detail_exit(1); } let compiler = self.compiler; diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 5be6841e988a..4e8ff75cc67c 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::env; use std::fs; use std::path::{Path, PathBuf}; -use std::process::{exit, Command}; +use std::process::Command; use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; use crate::channel::GitInfo; @@ -204,7 +204,7 @@ impl Step for ToolBuild { if !is_expected { if !is_optional_tool { - exit(1); + crate::detail_exit(1); } else { None } diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 3ee6a42d987a..2cfeae7dc785 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -93,7 +93,7 @@ fn print_error(tool: &str, submodule: &str) { eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool); eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule); eprintln!("proper steps."); - std::process::exit(3); + crate::detail_exit(3); } fn check_changed_files(toolstates: &HashMap, ToolState>) { @@ -108,7 +108,7 @@ fn check_changed_files(toolstates: &HashMap, ToolState>) { Ok(o) => o, Err(e) => { eprintln!("Failed to get changed files: {:?}", e); - std::process::exit(1); + crate::detail_exit(1); } }; @@ -179,7 +179,7 @@ impl Step for ToolStateCheck { } if did_error { - std::process::exit(1); + crate::detail_exit(1); } check_changed_files(&toolstates); @@ -225,7 +225,7 @@ impl Step for ToolStateCheck { } if did_error { - std::process::exit(1); + crate::detail_exit(1); } if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6f4266a7f294..b627e5037899 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -336,7 +336,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { if !try_run(cmd, print_cmd_on_fail) { - std::process::exit(1); + crate::detail_exit(1); } } @@ -375,7 +375,7 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { pub fn run_suppressed(cmd: &mut Command) { if !try_run_suppressed(cmd) { - std::process::exit(1); + crate::detail_exit(1); } } @@ -465,7 +465,7 @@ fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool { fn fail(s: &str) -> ! { eprintln!("\n\n{}\n\n", s); - std::process::exit(1); + crate::detail_exit(1); } /// Copied from `std::path::absolute` until it stabilizes.