diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 0e156b9d1ac9a..f7ecb4851529c 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,7 +1,6 @@
 run-make/branch-protection-check-IBT/Makefile
 run-make/cat-and-grep-sanity-check/Makefile
 run-make/extern-fn-reachable/Makefile
-run-make/incr-add-rust-src-component/Makefile
 run-make/jobserver-error/Makefile
 run-make/libs-through-symlinks/Makefile
 run-make/split-debuginfo/Makefile
diff --git a/tests/run-make/incr-add-rust-src-component/Makefile b/tests/run-make/incr-add-rust-src-component/Makefile
deleted file mode 100644
index fd09c2299f98e..0000000000000
--- a/tests/run-make/incr-add-rust-src-component/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# rust-lang/rust#70924: Test that if we add rust-src component in between two
-# incremental compiles, the compiler does not ICE on the second.
-
-# This test uses `ln -s` rather than copying to save testing time, but its
-# usage doesn't work on windows. So ignore windows.
-
-# ignore-windows
-
-SYSROOT:=$(shell $(RUSTC) --print sysroot)
-FAKEROOT=$(TMPDIR)/fakeroot
-INCR=$(TMPDIR)/incr
-
-# Make a local copy of the sysroot; then remove the rust-src part of it, if
-# present, for the *first* build. Then put in a facsimile of the rust-src
-# component for the second build, in order to expose the ICE from issue #70924.
-#
-# Note that it is much easier to just do `cp -a $(SYSROOT)/* $(FAKEROOT)` as a
-# first step, but I am concerned that would be too expensive in a unit test
-# compared to making symbolic links.
-#
-# Anyway, the pattern you'll see here is: For every prefix in
-# root/lib/rustlib/src, link all of prefix parent content, then remove the
-# prefix, then loop on the next prefix. This way, we basically create a copy of
-# the context around root/lib/rustlib/src, and can freely add/remove the src
-# component itself.
-all:
-	mkdir $(FAKEROOT)
-	ln -s $(SYSROOT)/* $(FAKEROOT)
-	rm -f $(FAKEROOT)/lib
-	mkdir $(FAKEROOT)/lib
-	ln -s $(SYSROOT)/lib/* $(FAKEROOT)/lib
-	rm -f $(FAKEROOT)/lib/rustlib
-	mkdir $(FAKEROOT)/lib/rustlib
-	ln -s $(SYSROOT)/lib/rustlib/* $(FAKEROOT)/lib/rustlib
-	rm -f $(FAKEROOT)/lib/rustlib/src
-	mkdir $(FAKEROOT)/lib/rustlib/src
-	ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src
-	rm -f $(FAKEROOT)/lib/rustlib/src/rust
-	$(RUSTC) --sysroot $(FAKEROOT) -C incremental=$(INCR) main.rs
-	mkdir -p $(FAKEROOT)/lib/rustlib/src/rust/src/libstd
-	touch $(FAKEROOT)/lib/rustlib/src/rust/src/libstd/lib.rs
-	$(RUSTC) --sysroot $(FAKEROOT) -C incremental=$(INCR) main.rs
diff --git a/tests/run-make/incr-add-rust-src-component/rmake.rs b/tests/run-make/incr-add-rust-src-component/rmake.rs
new file mode 100644
index 0000000000000..964f1410a9647
--- /dev/null
+++ b/tests/run-make/incr-add-rust-src-component/rmake.rs
@@ -0,0 +1,131 @@
+//! Regression test for rust-lang/rust#70924. Check that if we add the `rust-src` component in
+//! between two incremental compiles, that the compiler doesn't ICE on the second invocation.
+//!
+//! This test uses symbolic links to save testing time.
+//!
+//! The way this test works is that, for every prefix in `root/lib/rustlib/src`, link all of prefix
+//! parent content, then remove the prefix, then loop on the next prefix. This way, we basically
+//! create a copy of the context around `root/lib/rustlib/src`, and can freely add/remove the src
+//! component itself.
+
+//@ ignore-cross-compile
+// Reason: test needs to run.
+
+//@ needs-symlink
+// Reason: test needs symlink to create stub directories and files.
+
+use std::path::Path;
+
+use run_make_support::rfs::read_dir_entries;
+use run_make_support::{bare_rustc, path, rfs, run};
+
+#[derive(Debug, Copy, Clone)]
+struct Symlink<'a, 'b> {
+    src_dir: &'a Path,
+    dst_dir: &'b Path,
+}
+
+fn shallow_symlink_dir<'a, 'b>(Symlink { src_dir, dst_dir }: Symlink<'a, 'b>) {
+    eprintln!(
+        "shallow_symlink_dir: src_dir={} -> dst_dir={}",
+        src_dir.display(),
+        dst_dir.display()
+    );
+
+    read_dir_entries(src_dir, |src_path| {
+        let src_metadata = rfs::symlink_metadata(src_path);
+        let filename = src_path.file_name().unwrap();
+        if src_metadata.is_dir() {
+            rfs::symlink_dir(src_path, dst_dir.join(filename));
+        } else if src_metadata.is_file() {
+            rfs::symlink_file(src_path, dst_dir.join(filename));
+        } else if src_metadata.is_symlink() {
+            rfs::copy_symlink(src_path, dst_dir.join(filename));
+        }
+    });
+}
+
+fn recreate_dir(path: &Path) {
+    rfs::recursive_remove(path);
+    rfs::create_dir(path);
+}
+
+fn main() {
+    let sysroot = bare_rustc().print("sysroot").run().stdout_utf8();
+    let sysroot = sysroot.trim();
+    let sysroot = path(sysroot);
+
+    let incr = path("incr");
+
+    let fakeroot = path("fakeroot");
+    rfs::create_dir(&fakeroot);
+
+    shallow_symlink_dir(Symlink { src_dir: &sysroot, dst_dir: &fakeroot });
+    recreate_dir(&fakeroot.join("lib"));
+
+    shallow_symlink_dir(Symlink { src_dir: &sysroot.join("lib"), dst_dir: &fakeroot.join("lib") });
+    recreate_dir(&fakeroot.join("lib").join("rustlib"));
+
+    shallow_symlink_dir(Symlink {
+        src_dir: &sysroot.join("lib").join("rustlib"),
+        dst_dir: &fakeroot.join("lib").join("rustlib"),
+    });
+    recreate_dir(&fakeroot.join("lib").join("rustlib").join("src"));
+
+    shallow_symlink_dir(Symlink {
+        src_dir: &sysroot.join("lib").join("rustlib").join("src"),
+        dst_dir: &fakeroot.join("lib").join("rustlib").join("src"),
+    });
+
+    rfs::recursive_remove(&fakeroot.join("lib").join("rustlib").join("src").join("rust"));
+
+    let run_incr_rustc = || {
+        bare_rustc()
+            .sysroot(&fakeroot)
+            .arg("-C")
+            .arg(format!("incremental={}", incr.to_str().unwrap()))
+            .input("main.rs")
+            .run();
+    };
+
+    // Run rustc w/ incremental once...
+    run_incr_rustc();
+
+    // NOTE: the Makefile version of this used `$SYSROOT/lib/rustlib/src/rust/src/libstd/lib.rs`,
+    // but that actually got moved around and reorganized over the years. As of Dec 2024, the
+    // rust-src component is more like (specific for our purposes):
+    //
+    // ```
+    // $SYSROOT/lib/rustlib/src/rust/
+    //     library/std/src/lib.rs
+    //     src/
+    // ```
+    rfs::create_dir_all(
+        &fakeroot
+            .join("lib")
+            .join("rustlib")
+            .join("src")
+            .join("rust")
+            .join("library")
+            .join("std")
+            .join("src"),
+    );
+    rfs::write(
+        &fakeroot
+            .join("lib")
+            .join("rustlib")
+            .join("src")
+            .join("rust")
+            .join("library")
+            .join("std")
+            .join("src")
+            .join("lib.rs"),
+        b"",
+    );
+
+    // ... and a second time.
+    run_incr_rustc();
+
+    // Basic sanity check that the compiled binary can run.
+    run("main");
+}