about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-29 10:11:16 +0000
committerbors <bors@rust-lang.org>2021-01-29 10:11:16 +0000
commitc4e33b51c1a2d5e599b949fa3006467b88df253a (patch)
tree6650ae4a6bee22f1b5f37963ee346514a423e4fa
parent099f27b6cbf10e31d41e4a2e6cb55ec39dbb0527 (diff)
parent6c7ecd007f9c8fdf7f5cbbc01837cc04c81a781c (diff)
downloadrust-c4e33b51c1a2d5e599b949fa3006467b88df253a.tar.gz
rust-c4e33b51c1a2d5e599b949fa3006467b88df253a.zip
Auto merge of #81419 - rylev:canocalize-extern-entries, r=petrochenkov
Pre-canoncalize ExternLocation::ExactPaths

This stores pre-canacolized paths inside `ExternLocation::ExactPaths` so that we don't need to canoncalize them every time we want to compare them to source lib paths.

This is related to #81414.
-rw-r--r--compiler/rustc_interface/src/tests.rs7
-rw-r--r--compiler/rustc_metadata/src/creader.rs10
-rw-r--r--compiler/rustc_metadata/src/locator.rs24
-rw-r--r--compiler/rustc_session/src/config.rs10
-rw-r--r--compiler/rustc_session/src/utils.rs23
5 files changed, 54 insertions, 20 deletions
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 305ae23669b..31e29351856 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -11,7 +11,7 @@ use rustc_session::config::{
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
-use rustc_session::utils::NativeLibKind;
+use rustc_session::utils::{CanonicalizedPath, NativeLibKind};
 use rustc_session::{build_session, getopts, DiagnosticOutput, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
@@ -20,7 +20,7 @@ use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}
 use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel};
 use std::collections::{BTreeMap, BTreeSet};
 use std::iter::FromIterator;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
 type CfgSpecs = FxHashSet<(String, Option<String>)>;
 
@@ -50,7 +50,8 @@ where
     S: Into<String>,
     I: IntoIterator<Item = S>,
 {
-    let locations: BTreeSet<_> = locations.into_iter().map(|s| s.into()).collect();
+    let locations: BTreeSet<CanonicalizedPath> =
+        locations.into_iter().map(|s| CanonicalizedPath::new(Path::new(&s.into()))).collect();
 
     ExternEntry {
         location: ExternLocation::ExactPaths(locations),
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index f203094fc73..e3fbd1a2b29 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -28,7 +28,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
 
 use proc_macro::bridge::client::ProcMacro;
 use std::path::Path;
-use std::{cmp, env, fs};
+use std::{cmp, env};
 use tracing::{debug, info};
 
 #[derive(Clone)]
@@ -252,10 +252,10 @@ impl<'a> CrateLoader<'a> {
                 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
                 if let Some(mut files) = entry.files() {
                     if files.any(|l| {
-                        let l = fs::canonicalize(l).unwrap_or(l.clone().into());
-                        source.dylib.as_ref().map(|(p, _)| p) == Some(&l)
-                            || source.rlib.as_ref().map(|(p, _)| p) == Some(&l)
-                            || source.rmeta.as_ref().map(|(p, _)| p) == Some(&l)
+                        let l = l.canonicalized();
+                        source.dylib.as_ref().map(|(p, _)| p) == Some(l)
+                            || source.rlib.as_ref().map(|(p, _)| p) == Some(l)
+                            || source.rmeta.as_ref().map(|(p, _)| p) == Some(l)
                     }) {
                         ret = Some(cnum);
                     }
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index c4c025de8b3..b66c6cffb1b 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -224,6 +224,7 @@ use rustc_middle::middle::cstore::{CrateSource, MetadataLoader};
 use rustc_session::config::{self, CrateType};
 use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
 use rustc_session::search_paths::PathKind;
+use rustc_session::utils::CanonicalizedPath;
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
@@ -244,7 +245,7 @@ crate struct CrateLocator<'a> {
 
     // Immutable per-search configuration.
     crate_name: Symbol,
-    exact_paths: Vec<PathBuf>,
+    exact_paths: Vec<CanonicalizedPath>,
     pub hash: Option<Svh>,
     pub host_hash: Option<Svh>,
     extra_filename: Option<&'a str>,
@@ -315,7 +316,7 @@ impl<'a> CrateLocator<'a> {
                     .into_iter()
                     .filter_map(|entry| entry.files())
                     .flatten()
-                    .map(PathBuf::from)
+                    .cloned()
                     .collect()
             } else {
                 // SVH being specified means this is a transitive dependency,
@@ -664,13 +665,19 @@ impl<'a> CrateLocator<'a> {
         let mut rmetas = FxHashMap::default();
         let mut dylibs = FxHashMap::default();
         for loc in &self.exact_paths {
-            if !loc.exists() {
-                return Err(CrateError::ExternLocationNotExist(self.crate_name, loc.clone()));
+            if !loc.canonicalized().exists() {
+                return Err(CrateError::ExternLocationNotExist(
+                    self.crate_name,
+                    loc.original().clone(),
+                ));
             }
-            let file = match loc.file_name().and_then(|s| s.to_str()) {
+            let file = match loc.original().file_name().and_then(|s| s.to_str()) {
                 Some(file) => file,
                 None => {
-                    return Err(CrateError::ExternLocationNotFile(self.crate_name, loc.clone()));
+                    return Err(CrateError::ExternLocationNotFile(
+                        self.crate_name,
+                        loc.original().clone(),
+                    ));
                 }
             };
 
@@ -685,7 +692,8 @@ impl<'a> CrateLocator<'a> {
                 // e.g. symbolic links. If we canonicalize too early, we resolve
                 // the symlink, the file type is lost and we might treat rlibs and
                 // rmetas as dylibs.
-                let loc_canon = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
+                let loc_canon = loc.canonicalized().clone();
+                let loc = loc.original();
                 if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
                     rlibs.insert(loc_canon, PathKind::ExternFlag);
                 } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
@@ -695,7 +703,7 @@ impl<'a> CrateLocator<'a> {
                 }
             } else {
                 self.rejected_via_filename
-                    .push(CrateMismatch { path: loc.clone(), got: String::new() });
+                    .push(CrateMismatch { path: loc.original().clone(), got: String::new() });
             }
         }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index f9e40919149..9d73c3b4424 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -5,7 +5,7 @@ pub use crate::options::*;
 
 use crate::lint;
 use crate::search_paths::SearchPath;
-use crate::utils::NativeLibKind;
+use crate::utils::{CanonicalizedPath, NativeLibKind};
 use crate::{early_error, early_warn, Session};
 
 use rustc_data_structures::fx::FxHashSet;
@@ -436,7 +436,7 @@ pub enum ExternLocation {
     /// which one to use.
     ///
     /// Added via `--extern prelude_name=some_file.rlib`
-    ExactPaths(BTreeSet<String>),
+    ExactPaths(BTreeSet<CanonicalizedPath>),
 }
 
 impl Externs {
@@ -458,7 +458,7 @@ impl ExternEntry {
         ExternEntry { location, is_private_dep: false, add_prelude: false }
     }
 
-    pub fn files(&self) -> Option<impl Iterator<Item = &String>> {
+    pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
         match &self.location {
             ExternLocation::ExactPaths(set) => Some(set.iter()),
             _ => None,
@@ -1639,13 +1639,15 @@ pub fn parse_externs(
     for arg in matches.opt_strs("extern") {
         let (name, path) = match arg.split_once('=') {
             None => (arg, None),
-            Some((name, path)) => (name.to_string(), Some(path.to_string())),
+            Some((name, path)) => (name.to_string(), Some(Path::new(path))),
         };
         let (options, name) = match name.split_once(':') {
             None => (None, name),
             Some((opts, name)) => (Some(opts), name.to_string()),
         };
 
+        let path = path.map(|p| CanonicalizedPath::new(p));
+
         let entry = externs.entry(name.to_owned());
 
         use std::collections::btree_map::Entry;
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index 15447c01d1e..f3d33309124 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -1,5 +1,6 @@
 use crate::session::Session;
 use rustc_data_structures::profiling::VerboseTimingGuard;
+use std::path::{Path, PathBuf};
 
 impl Session {
     pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> {
@@ -30,3 +31,25 @@ pub enum NativeLibKind {
 }
 
 rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
+
+/// A path that has been canonicalized along with its original, non-canonicalized form
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct CanonicalizedPath {
+    // Optional since canonicalization can sometimes fail
+    canonicalized: Option<PathBuf>,
+    original: PathBuf,
+}
+
+impl CanonicalizedPath {
+    pub fn new(path: &Path) -> Self {
+        Self { original: path.to_owned(), canonicalized: std::fs::canonicalize(path).ok() }
+    }
+
+    pub fn canonicalized(&self) -> &PathBuf {
+        self.canonicalized.as_ref().unwrap_or(self.original())
+    }
+
+    pub fn original(&self) -> &PathBuf {
+        &self.original
+    }
+}