Skip to content

Commit 0a45b13

Browse files
authored
Rollup merge of #74915 - alexcrichton:allow-failing-canonicalize, r=Mark-Simulacrum
rustc: Ignore fs::canonicalize errors in metadata This commit updates the metadata location logic to ignore errors when calling `fs::canonicalize`. Canonicalization was added historically so multiple `-L` paths to the same directory don't print errors about multiple candidates (since rustc can deduplicate same-named paths), but canonicalization doesn't work on all filesystems. Cargo, for example, always uses this sort of fallback where it will opportunitistically try to canonicalize but fall back to using the input path if it otherwise doesn't work. If rustc is run on a filesystem that doesn't support canonicalization then the effect of this change will be that `-L` paths which logically point to the same directory will cause errors, but that's a rare enough occurrence it shouldn't cause much issue in practice. Otherwise rustc doesn't work at all today on those sorts of filesystem where canonicalization isn't supported!
2 parents 2c6c764 + cd8bdb5 commit 0a45b13

File tree

3 files changed

+31
-39
lines changed

3 files changed

+31
-39
lines changed

src/librustc_metadata/creader.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@ impl<'a> CrateLoader<'a> {
248248
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
249249
if let Some(mut files) = entry.files() {
250250
if files.any(|l| {
251-
let l = fs::canonicalize(l).ok();
252-
source.dylib.as_ref().map(|p| &p.0) == l.as_ref()
253-
|| source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
251+
let l = fs::canonicalize(l).unwrap_or(l.clone().into());
252+
source.dylib.as_ref().map(|p| &p.0) == Some(&l)
253+
|| source.rlib.as_ref().map(|p| &p.0) == Some(&l)
254254
}) {
255255
ret = Some(cnum);
256256
}

src/librustc_metadata/locator.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -426,20 +426,17 @@ impl<'a> CrateLocator<'a> {
426426
info!("lib candidate: {}", spf.path.display());
427427

428428
let (rlibs, rmetas, dylibs) = candidates.entry(hash.to_string()).or_default();
429-
fs::canonicalize(&spf.path)
430-
.map(|p| {
431-
if seen_paths.contains(&p) {
432-
return FileDoesntMatch;
433-
};
434-
seen_paths.insert(p.clone());
435-
match found_kind {
436-
CrateFlavor::Rlib => rlibs.insert(p, kind),
437-
CrateFlavor::Rmeta => rmetas.insert(p, kind),
438-
CrateFlavor::Dylib => dylibs.insert(p, kind),
439-
};
440-
FileMatches
441-
})
442-
.unwrap_or(FileDoesntMatch)
429+
let path = fs::canonicalize(&spf.path).unwrap_or_else(|_| spf.path.clone());
430+
if seen_paths.contains(&path) {
431+
return FileDoesntMatch;
432+
};
433+
seen_paths.insert(path.clone());
434+
match found_kind {
435+
CrateFlavor::Rlib => rlibs.insert(path, kind),
436+
CrateFlavor::Rmeta => rmetas.insert(path, kind),
437+
CrateFlavor::Dylib => dylibs.insert(path, kind),
438+
};
439+
FileMatches
443440
});
444441
self.rejected_via_kind.extend(staticlibs);
445442

@@ -688,12 +685,13 @@ impl<'a> CrateLocator<'a> {
688685
&& file.ends_with(&self.target.options.dll_suffix)
689686
{
690687
// Make sure there's at most one rlib and at most one dylib.
688+
let loc = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
691689
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
692-
rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
690+
rlibs.insert(loc, PathKind::ExternFlag);
693691
} else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
694-
rmetas.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
692+
rmetas.insert(loc, PathKind::ExternFlag);
695693
} else {
696-
dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
694+
dylibs.insert(loc, PathKind::ExternFlag);
697695
}
698696
} else {
699697
self.rejected_via_filename

src/librustc_session/filesearch.rs

+13-19
Original file line numberDiff line numberDiff line change
@@ -117,28 +117,22 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
117117

118118
pub fn get_or_default_sysroot() -> PathBuf {
119119
// Follow symlinks. If the resolved path is relative, make it absolute.
120-
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
121-
path.and_then(|path| {
122-
match fs::canonicalize(&path) {
123-
// See comments on this target function, but the gist is that
124-
// gcc chokes on verbatim paths which fs::canonicalize generates
125-
// so we try to avoid those kinds of paths.
126-
Ok(canon) => Some(fix_windows_verbatim_for_gcc(&canon)),
127-
Err(e) => panic!("failed to get realpath: {}", e),
128-
}
129-
})
120+
fn canonicalize(path: PathBuf) -> PathBuf {
121+
let path = fs::canonicalize(&path).unwrap_or(path);
122+
// See comments on this target function, but the gist is that
123+
// gcc chokes on verbatim paths which fs::canonicalize generates
124+
// so we try to avoid those kinds of paths.
125+
fix_windows_verbatim_for_gcc(&path)
130126
}
131127

132128
match env::current_exe() {
133-
Ok(exe) => match canonicalize(Some(exe)) {
134-
Some(mut p) => {
135-
p.pop();
136-
p.pop();
137-
p
138-
}
139-
None => panic!("can't determine value for sysroot"),
140-
},
141-
Err(ref e) => panic!(format!("failed to get current_exe: {}", e)),
129+
Ok(exe) => {
130+
let mut p = canonicalize(exe);
131+
p.pop();
132+
p.pop();
133+
p
134+
}
135+
Err(e) => panic!("failed to get current_exe: {}", e),
142136
}
143137
}
144138

0 commit comments

Comments
 (0)