From d0baf52669a252ae92ab43b4f80b183a906a4dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Thu, 20 Aug 2026 11:46:05 +0200 Subject: [PATCH] fix(test): resolve rustc without PATH in strip-dedup archive tests --- changelog.d/8473-strip-dedup-rustc-path.md | 1 + .../compile/strip_dedup/strip_dedup_tests.rs | 34 +++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 changelog.d/8473-strip-dedup-rustc-path.md diff --git a/changelog.d/8473-strip-dedup-rustc-path.md b/changelog.d/8473-strip-dedup-rustc-path.md new file mode 100644 index 00000000000..17b5145885b --- /dev/null +++ b/changelog.d/8473-strip-dedup-rustc-path.md @@ -0,0 +1 @@ +Resolve `rustc` without consulting `PATH` in the strip-dedup archive tests. Sibling tests in `optimized_libs/tests.rs` overwrite — and briefly remove — the process-global `PATH`, which is shared across test threads, so `Command::new("rustc")` failed with ENOENT whenever they ran concurrently. `cargo test -p perry --bin perry` was failing 6 of 6 runs on `main` at its default thread count. diff --git a/crates/perry/src/commands/compile/strip_dedup/strip_dedup_tests.rs b/crates/perry/src/commands/compile/strip_dedup/strip_dedup_tests.rs index 14ea52c08af..41bcdaee9c1 100644 --- a/crates/perry/src/commands/compile/strip_dedup/strip_dedup_tests.rs +++ b/crates/perry/src/commands/compile/strip_dedup/strip_dedup_tests.rs @@ -140,7 +140,22 @@ fn coff_archive_dedup_drops_only_fully_provided_members() { use std::process::Command; fn compile_object(source: &Path, output: &Path, crate_name: &str) { - let result = Command::new("rustc") + // Resolve rustc without consulting `PATH`. Sibling tests in + // `optimized_libs/tests.rs` overwrite — and briefly remove — the + // process-global `PATH`, and the environment is shared across test + // threads, so a bare-name spawn here fails with ENOENT whenever those + // run concurrently. Cargo exports `CARGO` to test binaries and rustc + // sits beside it in the same toolchain directory. See #8472. + let rustc = std::env::var_os("RUSTC") + .map(std::path::PathBuf::from) + .or_else(|| { + std::env::var_os("CARGO") + .map(std::path::PathBuf::from) + .and_then(|cargo| cargo.parent().map(|dir| dir.join("rustc"))) + .filter(|candidate| candidate.exists()) + }) + .unwrap_or_else(|| std::path::PathBuf::from("rustc")); + let result = Command::new(rustc) .arg("--crate-name") .arg(crate_name) .arg("--crate-type=lib") @@ -235,7 +250,22 @@ fn stdlib_evidence_gate_keeps_members_when_stdlib_is_not_linked() { use std::process::Command; fn compile_object(source: &Path, output: &Path, crate_name: &str) { - let result = Command::new("rustc") + // Resolve rustc without consulting `PATH`. Sibling tests in + // `optimized_libs/tests.rs` overwrite — and briefly remove — the + // process-global `PATH`, and the environment is shared across test + // threads, so a bare-name spawn here fails with ENOENT whenever those + // run concurrently. Cargo exports `CARGO` to test binaries and rustc + // sits beside it in the same toolchain directory. See #8472. + let rustc = std::env::var_os("RUSTC") + .map(std::path::PathBuf::from) + .or_else(|| { + std::env::var_os("CARGO") + .map(std::path::PathBuf::from) + .and_then(|cargo| cargo.parent().map(|dir| dir.join("rustc"))) + .filter(|candidate| candidate.exists()) + }) + .unwrap_or_else(|| std::path::PathBuf::from("rustc")); + let result = Command::new(rustc) .arg("--crate-name") .arg(crate_name) .arg("--crate-type=lib")