diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 833cbedd5cf8e..a3bac5bfe7a8a 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -28,13 +28,16 @@ pub struct Std {
     /// passing `Builder::kind` to cargo invocations would run clippy on the entire compiler and library,
     /// which is not useful if we only want to lint a few crates with specific rules.
     override_build_kind: Option<Kind>,
+    /// Never use this from outside calls. It is intended for internal use only within `check::Std::make_run`
+    /// and `check::Std::run`.
+    custom_stage: Option<u32>,
 }
 
 impl Std {
     const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
 
     pub fn new(target: TargetSelection) -> Self {
-        Self { target, crates: vec![], override_build_kind: None }
+        Self { target, crates: vec![], override_build_kind: None, custom_stage: None }
     }
 
     pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
@@ -48,34 +51,35 @@ impl Step for Std {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let builder = run.builder;
-        let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
-            builder.top_stage
-        } else {
-            1
-        };
-
         let mut run = run;
         for c in Std::CRATE_OR_DEPS {
             run = run.crate_or_deps(c);
         }
 
-        run.path("library").default_condition(stage != 0)
+        run.path("library")
     }
 
     fn make_run(run: RunConfig<'_>) {
         let crates = std_crates_for_run_make(&run);
-        run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
+
+        let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 1 {
+            run.builder.top_stage
+        } else {
+            1
+        };
+
+        run.builder.ensure(Std {
+            target: run.target,
+            crates,
+            override_build_kind: None,
+            custom_stage: Some(stage),
+        });
     }
 
     fn run(self, builder: &Builder<'_>) {
         builder.require_submodule("library/stdarch", None);
 
-        let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
-            builder.top_stage
-        } else {
-            1
-        };
+        let stage = self.custom_stage.unwrap_or(builder.top_stage);
 
         let target = self.target;
         let compiler = builder.compiler(stage, builder.config.build);
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 22a458bac981c..dddce8fe05d1d 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2707,16 +2707,6 @@ impl Step for Crate {
                         .arg(builder.src.join("library/sysroot/Cargo.toml"));
                 } else {
                     compile::std_cargo(builder, target, compiler.stage, &mut cargo);
-                    // `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`,
-                    // but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`.
-                    // Override it.
-                    if builder.download_rustc() && compiler.stage > 0 {
-                        let sysroot = builder
-                            .out
-                            .join(compiler.host)
-                            .join(format!("stage{}-test-sysroot", compiler.stage));
-                        cargo.env("RUSTC_SYSROOT", sysroot);
-                    }
                 }
             }
             Mode::Rustc => {
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index af3e3cc37b928..19b79bfe818c2 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -945,7 +945,6 @@ impl<'a> Builder<'a> {
                 clippy::CI,
             ),
             Kind::Check | Kind::Fix => describe!(
-                check::Std,
                 check::Rustc,
                 check::Rustdoc,
                 check::CodegenBackend,
@@ -961,6 +960,13 @@ impl<'a> Builder<'a> {
                 check::Compiletest,
                 check::FeaturesStatusDump,
                 check::CoverageDump,
+                // This has special staging logic, it may run on stage 1 while others run on stage 0.
+                // It takes quite some time to build stage 1, so put this at the end.
+                //
+                // FIXME: This also helps bootstrap to not interfere with stage 0 builds. We should probably fix
+                // that issue somewhere else, but we still want to keep `check::Std` at the end so that the
+                // quicker steps run before this.
+                check::Std,
             ),
             Kind::Test => describe!(
                 crate::core::build_steps::toolstate::ToolStateCheck,