Skip to content

Commit 6c7ecd0

Browse files
committed
Pre-canoncalize ExternLocation::ExactPaths
1 parent c6bc462 commit 6c7ecd0

File tree

5 files changed

+54
-20
lines changed

5 files changed

+54
-20
lines changed

Diff for: compiler/rustc_interface/src/tests.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_session::config::{
1111
};
1212
use rustc_session::lint::Level;
1313
use rustc_session::search_paths::SearchPath;
14-
use rustc_session::utils::NativeLibKind;
14+
use rustc_session::utils::{CanonicalizedPath, NativeLibKind};
1515
use rustc_session::{build_session, getopts, DiagnosticOutput, Session};
1616
use rustc_span::edition::{Edition, DEFAULT_EDITION};
1717
use rustc_span::symbol::sym;
@@ -20,7 +20,7 @@ use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}
2020
use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel};
2121
use std::collections::{BTreeMap, BTreeSet};
2222
use std::iter::FromIterator;
23-
use std::path::PathBuf;
23+
use std::path::{Path, PathBuf};
2424

2525
type CfgSpecs = FxHashSet<(String, Option<String>)>;
2626

@@ -50,7 +50,8 @@ where
5050
S: Into<String>,
5151
I: IntoIterator<Item = S>,
5252
{
53-
let locations: BTreeSet<_> = locations.into_iter().map(|s| s.into()).collect();
53+
let locations: BTreeSet<CanonicalizedPath> =
54+
locations.into_iter().map(|s| CanonicalizedPath::new(Path::new(&s.into()))).collect();
5455

5556
ExternEntry {
5657
location: ExternLocation::ExactPaths(locations),

Diff for: compiler/rustc_metadata/src/creader.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
2828

2929
use proc_macro::bridge::client::ProcMacro;
3030
use std::path::Path;
31-
use std::{cmp, env, fs};
31+
use std::{cmp, env};
3232
use tracing::{debug, info};
3333

3434
#[derive(Clone)]
@@ -252,10 +252,10 @@ impl<'a> CrateLoader<'a> {
252252
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
253253
if let Some(mut files) = entry.files() {
254254
if files.any(|l| {
255-
let l = fs::canonicalize(l).unwrap_or(l.clone().into());
256-
source.dylib.as_ref().map(|(p, _)| p) == Some(&l)
257-
|| source.rlib.as_ref().map(|(p, _)| p) == Some(&l)
258-
|| source.rmeta.as_ref().map(|(p, _)| p) == Some(&l)
255+
let l = l.canonicalized();
256+
source.dylib.as_ref().map(|(p, _)| p) == Some(l)
257+
|| source.rlib.as_ref().map(|(p, _)| p) == Some(l)
258+
|| source.rmeta.as_ref().map(|(p, _)| p) == Some(l)
259259
}) {
260260
ret = Some(cnum);
261261
}

Diff for: compiler/rustc_metadata/src/locator.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ use rustc_middle::middle::cstore::{CrateSource, MetadataLoader};
224224
use rustc_session::config::{self, CrateType};
225225
use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
226226
use rustc_session::search_paths::PathKind;
227+
use rustc_session::utils::CanonicalizedPath;
227228
use rustc_session::{CrateDisambiguator, Session};
228229
use rustc_span::symbol::{sym, Symbol};
229230
use rustc_span::Span;
@@ -244,7 +245,7 @@ crate struct CrateLocator<'a> {
244245

245246
// Immutable per-search configuration.
246247
crate_name: Symbol,
247-
exact_paths: Vec<PathBuf>,
248+
exact_paths: Vec<CanonicalizedPath>,
248249
pub hash: Option<Svh>,
249250
pub host_hash: Option<Svh>,
250251
extra_filename: Option<&'a str>,
@@ -315,7 +316,7 @@ impl<'a> CrateLocator<'a> {
315316
.into_iter()
316317
.filter_map(|entry| entry.files())
317318
.flatten()
318-
.map(PathBuf::from)
319+
.cloned()
319320
.collect()
320321
} else {
321322
// SVH being specified means this is a transitive dependency,
@@ -664,13 +665,19 @@ impl<'a> CrateLocator<'a> {
664665
let mut rmetas = FxHashMap::default();
665666
let mut dylibs = FxHashMap::default();
666667
for loc in &self.exact_paths {
667-
if !loc.exists() {
668-
return Err(CrateError::ExternLocationNotExist(self.crate_name, loc.clone()));
668+
if !loc.canonicalized().exists() {
669+
return Err(CrateError::ExternLocationNotExist(
670+
self.crate_name,
671+
loc.original().clone(),
672+
));
669673
}
670-
let file = match loc.file_name().and_then(|s| s.to_str()) {
674+
let file = match loc.original().file_name().and_then(|s| s.to_str()) {
671675
Some(file) => file,
672676
None => {
673-
return Err(CrateError::ExternLocationNotFile(self.crate_name, loc.clone()));
677+
return Err(CrateError::ExternLocationNotFile(
678+
self.crate_name,
679+
loc.original().clone(),
680+
));
674681
}
675682
};
676683

@@ -685,7 +692,8 @@ impl<'a> CrateLocator<'a> {
685692
// e.g. symbolic links. If we canonicalize too early, we resolve
686693
// the symlink, the file type is lost and we might treat rlibs and
687694
// rmetas as dylibs.
688-
let loc_canon = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
695+
let loc_canon = loc.canonicalized().clone();
696+
let loc = loc.original();
689697
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
690698
rlibs.insert(loc_canon, PathKind::ExternFlag);
691699
} else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
@@ -695,7 +703,7 @@ impl<'a> CrateLocator<'a> {
695703
}
696704
} else {
697705
self.rejected_via_filename
698-
.push(CrateMismatch { path: loc.clone(), got: String::new() });
706+
.push(CrateMismatch { path: loc.original().clone(), got: String::new() });
699707
}
700708
}
701709

Diff for: compiler/rustc_session/src/config.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub use crate::options::*;
55

66
use crate::lint;
77
use crate::search_paths::SearchPath;
8-
use crate::utils::NativeLibKind;
8+
use crate::utils::{CanonicalizedPath, NativeLibKind};
99
use crate::{early_error, early_warn, Session};
1010

1111
use rustc_data_structures::fx::FxHashSet;
@@ -436,7 +436,7 @@ pub enum ExternLocation {
436436
/// which one to use.
437437
///
438438
/// Added via `--extern prelude_name=some_file.rlib`
439-
ExactPaths(BTreeSet<String>),
439+
ExactPaths(BTreeSet<CanonicalizedPath>),
440440
}
441441

442442
impl Externs {
@@ -458,7 +458,7 @@ impl ExternEntry {
458458
ExternEntry { location, is_private_dep: false, add_prelude: false }
459459
}
460460

461-
pub fn files(&self) -> Option<impl Iterator<Item = &String>> {
461+
pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
462462
match &self.location {
463463
ExternLocation::ExactPaths(set) => Some(set.iter()),
464464
_ => None,
@@ -1639,13 +1639,15 @@ pub fn parse_externs(
16391639
for arg in matches.opt_strs("extern") {
16401640
let (name, path) = match arg.split_once('=') {
16411641
None => (arg, None),
1642-
Some((name, path)) => (name.to_string(), Some(path.to_string())),
1642+
Some((name, path)) => (name.to_string(), Some(Path::new(path))),
16431643
};
16441644
let (options, name) = match name.split_once(':') {
16451645
None => (None, name),
16461646
Some((opts, name)) => (Some(opts), name.to_string()),
16471647
};
16481648

1649+
let path = path.map(|p| CanonicalizedPath::new(p));
1650+
16491651
let entry = externs.entry(name.to_owned());
16501652

16511653
use std::collections::btree_map::Entry;

Diff for: compiler/rustc_session/src/utils.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::session::Session;
22
use rustc_data_structures::profiling::VerboseTimingGuard;
3+
use std::path::{Path, PathBuf};
34

45
impl Session {
56
pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> {
@@ -30,3 +31,25 @@ pub enum NativeLibKind {
3031
}
3132

3233
rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
34+
35+
/// A path that has been canonicalized along with its original, non-canonicalized form
36+
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
37+
pub struct CanonicalizedPath {
38+
// Optional since canonicalization can sometimes fail
39+
canonicalized: Option<PathBuf>,
40+
original: PathBuf,
41+
}
42+
43+
impl CanonicalizedPath {
44+
pub fn new(path: &Path) -> Self {
45+
Self { original: path.to_owned(), canonicalized: std::fs::canonicalize(path).ok() }
46+
}
47+
48+
pub fn canonicalized(&self) -> &PathBuf {
49+
self.canonicalized.as_ref().unwrap_or(self.original())
50+
}
51+
52+
pub fn original(&self) -> &PathBuf {
53+
&self.original
54+
}
55+
}

0 commit comments

Comments
 (0)