about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs30
-rw-r--r--src/bootstrap/src/core/config/config.rs14
-rw-r--r--src/bootstrap/src/core/config/tests.rs61
3 files changed, 99 insertions, 6 deletions
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index d335ce65ad5..02d6f205d80 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -293,17 +293,27 @@ impl Step for Cargo {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Cargo { stage: run.builder.top_stage, host: run.target });
+        // If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2
+        // as tests for this step don't work with a lower stage.
+        let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 {
+            run.builder.top_stage
+        } else {
+            2
+        };
+
+        run.builder.ensure(Cargo { stage, host: run.target });
     }
 
     /// Runs `cargo test` for `cargo` packaged with Rust.
     fn run(self, builder: &Builder<'_>) {
-        if self.stage < 2 {
-            eprintln!("WARNING: cargo tests on stage {} may not behave well.", self.stage);
+        let stage = self.stage;
+
+        if stage < 2 {
+            eprintln!("WARNING: cargo tests on stage {stage} may not behave well.");
             eprintln!("HELP: consider using stage 2");
         }
 
-        let compiler = builder.compiler(self.stage, self.host);
+        let compiler = builder.compiler(stage, self.host);
 
         let cargo = builder.ensure(tool::Cargo { compiler, target: self.host });
         let compiler = cargo.build_compiler;
@@ -340,7 +350,7 @@ impl Step for Cargo {
                 crates: vec!["cargo".into()],
                 target: self.host.triple.to_string(),
                 host: self.host.triple.to_string(),
-                stage: self.stage,
+                stage,
             },
             builder,
         );
@@ -739,7 +749,15 @@ impl Step for Clippy {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Clippy { stage: run.builder.top_stage, host: run.target });
+        // If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2
+        // as tests for this step don't work with a lower stage.
+        let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 {
+            run.builder.top_stage
+        } else {
+            2
+        };
+
+        run.builder.ensure(Clippy { stage, host: run.target });
     }
 
     /// Runs `cargo test` for clippy.
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index d4b72ead045..2be42f16e2a 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -218,6 +218,8 @@ pub struct Config {
     pub stderr_is_tty: bool,
 
     pub on_fail: Option<String>,
+    pub explicit_stage_from_cli: bool,
+    pub explicit_stage_from_config: bool,
     pub stage: u32,
     pub keep_stage: Vec<u32>,
     pub keep_stage_std: Vec<u32>,
@@ -2323,6 +2325,14 @@ impl Config {
         config.compiletest_diff_tool = compiletest_diff_tool;
 
         let download_rustc = config.download_rustc_commit.is_some();
+        config.explicit_stage_from_cli = flags.stage.is_some();
+        config.explicit_stage_from_config = test_stage.is_some()
+            || build_stage.is_some()
+            || doc_stage.is_some()
+            || dist_stage.is_some()
+            || install_stage.is_some()
+            || check_stage.is_some()
+            || bench_stage.is_some();
         // See https://github.com/rust-lang/compiler-team/issues/326
         config.stage = match config.cmd {
             Subcommand::Check { .. } => flags.stage.or(check_stage).unwrap_or(0),
@@ -2392,6 +2402,10 @@ impl Config {
         }
     }
 
+    pub fn is_explicit_stage(&self) -> bool {
+        self.explicit_stage_from_cli || self.explicit_stage_from_config
+    }
+
     /// Runs a command, printing out nice contextual information if it fails.
     /// Exits if the command failed to execute at all, otherwise returns its
     /// `status.success()`.
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index f0a185ee3a7..eff5e033742 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -454,3 +454,64 @@ fn check_rustc_if_unchanged_paths() {
         assert!(config.src.join(p).exists(), "{p} doesn't exist.");
     }
 }
+
+#[test]
+fn test_explicit_stage() {
+    let config = Config::parse_inner(
+        Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]),
+        |&_| {
+            toml::from_str(
+                r#"
+            [build]
+            test-stage = 1
+        "#,
+            )
+        },
+    );
+
+    assert!(!config.explicit_stage_from_cli);
+    assert!(config.explicit_stage_from_config);
+    assert!(config.is_explicit_stage());
+
+    let config = Config::parse_inner(
+        Flags::parse(&[
+            "check".to_owned(),
+            "--stage=2".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+        ]),
+        |&_| toml::from_str(""),
+    );
+
+    assert!(config.explicit_stage_from_cli);
+    assert!(!config.explicit_stage_from_config);
+    assert!(config.is_explicit_stage());
+
+    let config = Config::parse_inner(
+        Flags::parse(&[
+            "check".to_owned(),
+            "--stage=2".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+        ]),
+        |&_| {
+            toml::from_str(
+                r#"
+            [build]
+            test-stage = 1
+        "#,
+            )
+        },
+    );
+
+    assert!(config.explicit_stage_from_cli);
+    assert!(config.explicit_stage_from_config);
+    assert!(config.is_explicit_stage());
+
+    let config = Config::parse_inner(
+        Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]),
+        |&_| toml::from_str(""),
+    );
+
+    assert!(!config.explicit_stage_from_cli);
+    assert!(!config.explicit_stage_from_config);
+    assert!(!config.is_explicit_stage());
+}