Change:
} // Copy the compiler into the correct sysroot. <del> builder.cp_r(&builder.ci_rustc_dir(builder.build.build), &sysroot); </del> <ins> // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're requested with `builder.ensure(Rustc)`. // This fixes an issue where we'd have multiple copies of libc in the sysroot with no way to tell which to load. // There are a few quirks of bootstrap that interact to make this reliable: // 1. The order `Step`s are run is hard-coded in `builder.rs` and not configurable. This //    avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter to //    fail because of duplicate metadata. // 2. The sysroot is deleted and recreated between each invocation, so running `x test //    ui-fulldeps && x test ui` can't cause failures. let mut filtered_files = Vec::new(); // Don't trim directories or files that aren't loaded per-target; they can't cause conflicts. let suffix = format!("lib/rustlib/{}/lib", compiler.host); for path in builder.config.rustc_dev_contents() { let path = Path::new(&path); if path.parent().map_or(false, |parent| parent.ends_with(&suffix)) { filtered_files.push(path.file_name().unwrap().to_owned()); } } let filtered_extensions = [OsStr::new("rmeta"), OsStr::new("rlib"), OsStr::new("so")]; let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build); builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| { if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) { return true; } if !path.parent().map_or(true, |p| p.ends_with(&suffix)) { return true; } if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) { builder.verbose_than(1, &format!("ignoring {}", path.display())); false } else { true } }); </ins> return INTERNER.intern_path(sysroot); }

Discussion:
cc I tried this: I expected to see this happen: The tests pass. Instead, this happened: The tests fail: These tests are pretty complicated but the error message looks correct: I'm not sure why both files are there and particularly why they have different hashes. shows that is being downloaded from CI, and I guess the is coming from somewhere - maybe we should clear the directory before doing that? <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --HEAD is <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim
Ok, it turns out both versions are coming from CI: I am ... surprised this hasn't broken anything else? I don't know why only this specific test would be failing.
The difference between this test and others is that somehow in other tests knows ahead of time which hash it should use: for the allocator tests, it doesn't know, and gives an ambiguity error:
ok, here's a minimal reproducer: I think what's going on is for the working tests, the implicit injected by the compiler also loads libc, because std depends on libc: Then, when the compiler sees , it's already seen the version depends on and resolves the ambiguity by reusing that crate. But for the failing test, we never load std, so we don't have a pre-existing hash to default to, so it gives a hard ambiguity error.