Rollup merge of #139834 - ChrisDenton:spf, r=WaffleLapkin

Don't canonicalize crate paths

When printing paths in diagnostic we should favour printing the paths that were passed in rather than resolving all symlinks.

This PR changes the form of the crate path but it should only really affect diagnostics as filesystem functions won't care which path is used. The uncanonicalized path was already used as a fallback for when canonicalization failed.

This is a partial alternative to #139823.
This commit is contained in:
Chris Denton 2025-04-19 15:09:35 +00:00 committed by GitHub
commit 2d4f1130a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 76 additions and 6 deletions

View file

@ -427,12 +427,21 @@ impl<'a> CrateLocator<'a> {
let (rlibs, rmetas, dylibs) =
candidates.entry(hash.to_string()).or_default();
let path =
try_canonicalize(&spf.path).unwrap_or_else(|_| spf.path.to_path_buf());
if seen_paths.contains(&path) {
continue;
};
seen_paths.insert(path.clone());
{
// As a perforamnce optimisation we canonicalize the path and skip
// ones we've already seeen. This allows us to ignore crates
// we know are exactual equal to ones we've already found.
// Going to the same crate through different symlinks does not change the result.
let path = try_canonicalize(&spf.path)
.unwrap_or_else(|_| spf.path.to_path_buf());
if seen_paths.contains(&path) {
continue;
};
seen_paths.insert(path);
}
// Use the original path (potentially with unresolved symlinks),
// filesystem code should not care, but this is nicer for diagnostics.
let path = spf.path.to_path_buf();
match kind {
CrateFlavor::Rlib => rlibs.insert(path, search_path.kind),
CrateFlavor::Rmeta => rmetas.insert(path, search_path.kind),

View file

@ -0,0 +1,6 @@
#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> isize {
10
}

View file

@ -0,0 +1,6 @@
#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> isize {
20
}

View file

@ -0,0 +1,3 @@
extern crate crateresolve1;
fn main() {}

View file

@ -0,0 +1,12 @@
error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found
--> multiple-candidates.rs:1:1
|
LL | extern crate crateresolve1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: candidate #1: ./mylibs/libcrateresolve1-1.rlib
= note: candidate #2: ./mylibs/libcrateresolve1-2.rlib
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0464`.

View file

@ -0,0 +1,34 @@
//@ needs-symlink
//@ ignore-cross-compile
// Tests that the multiple candidate dependencies diagnostic prints relative
// paths if a relative library path was passed in.
use run_make_support::{bare_rustc, diff, rfs, rustc};
fn main() {
// Check that relative paths are preserved in the diagnostic
rfs::create_dir("mylibs");
rustc().input("crateresolve1-1.rs").out_dir("mylibs").extra_filename("-1").run();
rustc().input("crateresolve1-2.rs").out_dir("mylibs").extra_filename("-2").run();
check("./mylibs");
// Check that symlinks aren't followed when printing the diagnostic
rfs::rename("mylibs", "original");
rfs::symlink_dir("original", "mylibs");
check("./mylibs");
}
fn check(library_path: &str) {
let out = rustc()
.input("multiple-candidates.rs")
.library_search_path(library_path)
.ui_testing()
.run_fail()
.stderr_utf8();
diff()
.expected_file("multiple-candidates.stderr")
.normalize(r"\\", "/")
.actual_text("(rustc)", &out)
.run();
}