about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2020-05-29 11:31:55 -0400
committerFelix S. Klock II <pnkfelix@pnkfx.org>2020-05-29 23:41:45 -0400
commitda09fd3db0c71680e16311140d07e8f1e079af82 (patch)
tree63100f855b06ffe43d5cd9f4dba9489e20babf54
parent905d738b1af874e248b9fe7fe4b115458975d401 (diff)
downloadrust-da09fd3db0c71680e16311140d07e8f1e079af82.tar.gz
rust-da09fd3db0c71680e16311140d07e8f1e079af82.zip
Split payload of FileName::Real to track both real and virutalized paths.
Such splits arise from metadata refs into libstd.

This way, we can (in a follow on commit) continue to emit the virtual name into
things like the like the StableSourceFileId that ends up in incremetnal build
artifacts, while still using the devirtualized file path when we want to access
the file.

Note that this commit is intended to be a refactoring; the actual fix to the bug
in question is in a follow-on commit.
-rw-r--r--src/librustc_expand/base.rs2
-rw-r--r--src/librustc_expand/expand.rs2
-rw-r--r--src/librustc_expand/module.rs5
-rw-r--r--src/librustc_expand/proc_macro_server.rs3
-rw-r--r--src/librustc_interface/passes.rs11
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs25
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs1
-rw-r--r--src/librustc_save_analysis/span_utils.rs5
-rw-r--r--src/librustc_span/lib.rs48
-rw-r--r--src/librustc_span/source_map.rs25
-rw-r--r--src/librustdoc/html/render.rs5
-rw-r--r--src/librustdoc/html/render/cache.rs2
-rw-r--r--src/librustdoc/html/sources.rs4
-rw-r--r--src/librustdoc/test.rs4
14 files changed, 103 insertions, 39 deletions
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 649aac488fc..3a06770e31b 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -1095,7 +1095,7 @@ impl<'a> ExtCtxt<'a> {
         if !path.is_absolute() {
             let callsite = span.source_callsite();
             let mut result = match self.source_map().span_to_unmapped_path(callsite) {
-                FileName::Real(path) => path,
+                FileName::Real(name) => name.into_local_path(),
                 FileName::DocTest(path, _) => path,
                 other => {
                     return Err(self.struct_span_err(
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index b505302f625..25b94ff2cbe 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -340,7 +340,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         let mut module = ModuleData {
             mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
             directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
-                FileName::Real(path) => path,
+                FileName::Real(name) => name.into_local_path(),
                 other => PathBuf::from(other.to_string()),
             },
         };
diff --git a/src/librustc_expand/module.rs b/src/librustc_expand/module.rs
index 9bb2b57b7f5..82215c7297e 100644
--- a/src/librustc_expand/module.rs
+++ b/src/librustc_expand/module.rs
@@ -71,7 +71,7 @@ crate fn parse_external_mod(
     // Extract the directory path for submodules of `module`.
     let path = sess.source_map().span_to_unmapped_path(module.inner);
     let mut path = match path {
-        FileName::Real(path) => path,
+        FileName::Real(name) => name.into_local_path(),
         other => PathBuf::from(other.to_string()),
     };
     path.pop();
@@ -189,7 +189,8 @@ fn error_cannot_declare_mod_here<'a, T>(
     let mut err =
         sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location");
     if !span.is_dummy() {
-        if let FileName::Real(src_path) = sess.source_map().span_to_filename(span) {
+        if let FileName::Real(src_name) = sess.source_map().span_to_filename(span) {
+            let src_path = src_name.into_local_path();
             if let Some(stem) = src_path.file_stem() {
                 let mut dest_path = src_path.clone();
                 dest_path.set_file_name(stem);
diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs
index b9693c2c862..36af83711f7 100644
--- a/src/librustc_expand/proc_macro_server.rs
+++ b/src/librustc_expand/proc_macro_server.rs
@@ -602,7 +602,8 @@ impl server::SourceFile for Rustc<'_> {
     }
     fn path(&mut self, file: &Self::SourceFile) -> String {
         match file.name {
-            FileName::Real(ref path) => path
+            FileName::Real(ref name) => name
+                .local_path()
                 .to_str()
                 .expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
                 .to_string(),
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 214701db724..9f1f38efb48 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -33,7 +33,7 @@ use rustc_session::output::{filename_for_input, filename_for_metadata};
 use rustc_session::search_paths::PathKind;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_span::FileName;
+use rustc_span::{FileName, RealFileName};
 use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
 
@@ -569,13 +569,16 @@ fn write_out_deps(
                 for cnum in resolver.cstore().crates_untracked() {
                     let source = resolver.cstore().crate_source_untracked(cnum);
                     if let Some((path, _)) = source.dylib {
-                        files.push(escape_dep_filename(&FileName::Real(path)));
+                        let file_name = FileName::Real(RealFileName::Named(path));
+                        files.push(escape_dep_filename(&file_name));
                     }
                     if let Some((path, _)) = source.rlib {
-                        files.push(escape_dep_filename(&FileName::Real(path)));
+                        let file_name = FileName::Real(RealFileName::Named(path));
+                        files.push(escape_dep_filename(&file_name));
                     }
                     if let Some((path, _)) = source.rmeta {
-                        files.push(escape_dep_filename(&FileName::Real(path)));
+                        let file_name = FileName::Real(RealFileName::Named(path));
+                        files.push(escape_dep_filename(&file_name));
                     }
                 }
             });
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 2b292b35c15..f5a9dceb782 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -1471,15 +1471,22 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
             if let Some(virtual_dir) = virtual_rust_source_base_dir {
                 if let Some(real_dir) = &sess.real_rust_source_base_dir {
-                    if let rustc_span::FileName::Real(path) = name {
-                        if let Ok(rest) = path.strip_prefix(virtual_dir) {
-                            let new_path = real_dir.join(rest);
-                            debug!(
-                                "try_to_translate_virtual_to_real: `{}` -> `{}`",
-                                path.display(),
-                                new_path.display(),
-                            );
-                            *path = new_path;
+                    if let rustc_span::FileName::Real(old_name) = name {
+                        if let rustc_span::RealFileName::Named(one_path) = old_name {
+                            if let Ok(rest) = one_path.strip_prefix(virtual_dir) {
+                                let virtual_name = one_path.clone();
+                                let new_path = real_dir.join(rest);
+                                debug!(
+                                    "try_to_translate_virtual_to_real: `{}` -> `{}`",
+                                    virtual_name.display(),
+                                    new_path.display(),
+                                );
+                                let new_name = rustc_span::RealFileName::Devirtualized {
+                                    local_path: new_path,
+                                    virtual_name,
+                                };
+                                *old_name = new_name;
+                            }
                         }
                     }
                 }
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 91fbfcc0133..b47a166feb5 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -396,6 +396,7 @@ impl<'tcx> EncodeContext<'tcx> {
                     // any relative paths are potentially relative to a
                     // wrong directory.
                     FileName::Real(ref name) => {
+                        let name = name.local_path();
                         let mut adapted = (**source_file).clone();
                         adapted.name = Path::new(&working_dir).join(name).into();
                         adapted.name_hash = {
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index 6620941c440..d5f992b0de0 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -16,12 +16,13 @@ impl<'a> SpanUtils<'a> {
 
     pub fn make_filename_string(&self, file: &SourceFile) -> String {
         match &file.name {
-            FileName::Real(path) if !file.name_was_remapped => {
+            FileName::Real(name) if !file.name_was_remapped => {
+                let path = name.local_path();
                 if path.is_absolute() {
                     self.sess
                         .source_map()
                         .path_mapping()
-                        .map_prefix(path.clone())
+                        .map_prefix(path.into())
                         .0
                         .display()
                         .to_string()
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index 58cdb87158a..f18a863d720 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -53,7 +53,7 @@ use std::cmp::{self, Ordering};
 use std::fmt;
 use std::hash::Hash;
 use std::ops::{Add, Sub};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::str::FromStr;
 
 use md5::Md5;
@@ -81,11 +81,45 @@ impl Globals {
 
 scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
 
+/// FIXME: Perhaps this should not implement Rustc{Decodable, Encodable}
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
+#[derive(HashStable_Generic)]
+pub enum RealFileName {
+    Named(PathBuf),
+    /// For de-virtualized paths (namely paths into libstd that have been mapped
+    /// to the appropriate spot on the local host's file system),
+    Devirtualized {
+        /// `local_path` is the (host-dependent) local path to the file.
+        local_path: PathBuf,
+        /// `virtual_name` is the stable path rustc will store internally within
+        /// build artifacts.
+        virtual_name: PathBuf,
+    },
+}
+
+impl RealFileName {
+    /// Returns the path suitable for reading from the file system on the local host.
+    pub fn local_path(&self) -> &Path {
+        match self {
+            RealFileName::Named(p)
+            | RealFileName::Devirtualized { local_path: p, virtual_name: _ } => &p,
+        }
+    }
+
+    /// Returns the path suitable for reading from the file system on the local host.
+    pub fn into_local_path(self) -> PathBuf {
+        match self {
+            RealFileName::Named(p)
+            | RealFileName::Devirtualized { local_path: p, virtual_name: _ } => p,
+        }
+    }
+}
+
 /// Differentiates between real files and common virtual files.
 #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
 #[derive(HashStable_Generic)]
 pub enum FileName {
-    Real(PathBuf),
+    Real(RealFileName),
     /// Call to `quote!`.
     QuoteExpansion(u64),
     /// Command line.
@@ -107,7 +141,13 @@ impl std::fmt::Display for FileName {
     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         use FileName::*;
         match *self {
-            Real(ref path) => write!(fmt, "{}", path.display()),
+            Real(RealFileName::Named(ref path)) => write!(fmt, "{}", path.display()),
+            // FIXME: might be nice to display both compoments of Devirtualized.
+            // But for now (to backport fix for issue #70924), best to not
+            // perturb diagnostics so its obvious test suite still works.
+            Real(RealFileName::Devirtualized { ref local_path, virtual_name: _ }) => {
+                write!(fmt, "{}", local_path.display())
+            }
             QuoteExpansion(_) => write!(fmt, "<quote expansion>"),
             MacroExpansion(_) => write!(fmt, "<macro expansion>"),
             Anon(_) => write!(fmt, "<anon>"),
@@ -123,7 +163,7 @@ impl std::fmt::Display for FileName {
 impl From<PathBuf> for FileName {
     fn from(p: PathBuf) -> Self {
         assert!(!p.to_string_lossy().ends_with('>'));
-        FileName::Real(p)
+        FileName::Real(RealFileName::Named(p))
     }
 }
 
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index dc85f7990b9..c432de3e847 100644
--- a/src/librustc_span/source_map.rs
+++ b/src/librustc_span/source_map.rs
@@ -235,7 +235,7 @@ impl SourceMap {
 
     fn try_new_source_file(
         &self,
-        filename: FileName,
+        mut filename: FileName,
         src: String,
     ) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
         // The path is used to determine the directory for loading submodules and
@@ -245,13 +245,22 @@ impl SourceMap {
         // be empty, so the working directory will be used.
         let unmapped_path = filename.clone();
 
-        let (filename, was_remapped) = match filename {
-            FileName::Real(filename) => {
-                let (filename, was_remapped) = self.path_mapping.map_prefix(filename);
-                (FileName::Real(filename), was_remapped)
+        let was_remapped;
+        if let FileName::Real(real_filename) = &mut filename {
+            match real_filename {
+                RealFileName::Named(path_to_be_remapped)
+                | RealFileName::Devirtualized {
+                    local_path: path_to_be_remapped,
+                    virtual_name: _,
+                } => {
+                    let mapped = self.path_mapping.map_prefix(path_to_be_remapped.clone());
+                    was_remapped = mapped.1;
+                    *path_to_be_remapped = mapped.0;
+                }
             }
-            other => (other, false),
-        };
+        } else {
+            was_remapped = false;
+        }
 
         let file_id =
             StableSourceFileId::new_from_pieces(&filename, was_remapped, Some(&unmapped_path));
@@ -998,7 +1007,7 @@ impl SourceMap {
     }
     pub fn ensure_source_file_source_present(&self, source_file: Lrc<SourceFile>) -> bool {
         source_file.add_external_src(|| match source_file.name {
-            FileName::Real(ref name) => self.file_loader.read_file(name).ok(),
+            FileName::Real(ref name) => self.file_loader.read_file(name.local_path()).ok(),
             _ => None,
         })
     }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index cd49da88d96..f6fb10b0180 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -473,7 +473,7 @@ pub fn run(
     } = options;
 
     let src_root = match krate.src {
-        FileName::Real(ref p) => match p.parent() {
+        FileName::Real(ref p) => match p.local_path().parent() {
             Some(p) => p.to_path_buf(),
             None => PathBuf::new(),
         },
@@ -1621,9 +1621,10 @@ impl Context {
 
         // We can safely ignore synthetic `SourceFile`s.
         let file = match item.source.filename {
-            FileName::Real(ref path) => path,
+            FileName::Real(ref path) => path.local_path().to_path_buf(),
             _ => return None,
         };
+        let file = &file;
 
         let (krate, path) = if item.source.cnum == LOCAL_CRATE {
             if let Some(path) = self.shared.local_sources.get(file) {
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 57d385de320..22594077341 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -173,7 +173,7 @@ impl Cache {
         // Cache where all our extern crates are located
         for &(n, ref e) in &krate.externs {
             let src_root = match e.src {
-                FileName::Real(ref p) => match p.parent() {
+                FileName::Real(ref p) => match p.local_path().parent() {
                     Some(p) => p.to_path_buf(),
                     None => PathBuf::new(),
                 },
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index c5f44baced2..018c0e82c45 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -67,10 +67,10 @@ impl<'a> SourceCollector<'a> {
     /// Renders the given filename into its corresponding HTML source file.
     fn emit_source(&mut self, filename: &FileName) -> Result<(), Error> {
         let p = match *filename {
-            FileName::Real(ref file) => file,
+            FileName::Real(ref file) => file.local_path().to_path_buf(),
             _ => return Ok(()),
         };
-        if self.scx.local_sources.contains_key(&**p) {
+        if self.scx.local_sources.contains_key(&*p) {
             // We've already emitted this source
             return Ok(());
         }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 284e6d421ee..ad7f2c112c1 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -688,7 +688,7 @@ impl Collector {
             let filename = source_map.span_to_filename(self.position);
             if let FileName::Real(ref filename) = filename {
                 if let Ok(cur_dir) = env::current_dir() {
-                    if let Ok(path) = filename.strip_prefix(&cur_dir) {
+                    if let Ok(path) = filename.local_path().strip_prefix(&cur_dir) {
                         return path.to_owned().into();
                     }
                 }
@@ -718,7 +718,7 @@ impl Tester for Collector {
         // FIXME(#44940): if doctests ever support path remapping, then this filename
         // needs to be the result of `SourceMap::span_to_unmapped_path`.
         let path = match &filename {
-            FileName::Real(path) => path.clone(),
+            FileName::Real(path) => path.local_path().to_path_buf(),
             _ => PathBuf::from(r"doctest.rs"),
         };