Skip to content

Commit da09fd3

Browse files
committed
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.
1 parent 905d738 commit da09fd3

File tree

14 files changed

+103
-39
lines changed

14 files changed

+103
-39
lines changed

src/librustc_expand/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,7 @@ impl<'a> ExtCtxt<'a> {
10951095
if !path.is_absolute() {
10961096
let callsite = span.source_callsite();
10971097
let mut result = match self.source_map().span_to_unmapped_path(callsite) {
1098-
FileName::Real(path) => path,
1098+
FileName::Real(name) => name.into_local_path(),
10991099
FileName::DocTest(path, _) => path,
11001100
other => {
11011101
return Err(self.struct_span_err(

src/librustc_expand/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
340340
let mut module = ModuleData {
341341
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
342342
directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
343-
FileName::Real(path) => path,
343+
FileName::Real(name) => name.into_local_path(),
344344
other => PathBuf::from(other.to_string()),
345345
},
346346
};

src/librustc_expand/module.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ crate fn parse_external_mod(
7171
// Extract the directory path for submodules of `module`.
7272
let path = sess.source_map().span_to_unmapped_path(module.inner);
7373
let mut path = match path {
74-
FileName::Real(path) => path,
74+
FileName::Real(name) => name.into_local_path(),
7575
other => PathBuf::from(other.to_string()),
7676
};
7777
path.pop();
@@ -189,7 +189,8 @@ fn error_cannot_declare_mod_here<'a, T>(
189189
let mut err =
190190
sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location");
191191
if !span.is_dummy() {
192-
if let FileName::Real(src_path) = sess.source_map().span_to_filename(span) {
192+
if let FileName::Real(src_name) = sess.source_map().span_to_filename(span) {
193+
let src_path = src_name.into_local_path();
193194
if let Some(stem) = src_path.file_stem() {
194195
let mut dest_path = src_path.clone();
195196
dest_path.set_file_name(stem);

src/librustc_expand/proc_macro_server.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,8 @@ impl server::SourceFile for Rustc<'_> {
602602
}
603603
fn path(&mut self, file: &Self::SourceFile) -> String {
604604
match file.name {
605-
FileName::Real(ref path) => path
605+
FileName::Real(ref name) => name
606+
.local_path()
606607
.to_str()
607608
.expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
608609
.to_string(),

src/librustc_interface/passes.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use rustc_session::output::{filename_for_input, filename_for_metadata};
3333
use rustc_session::search_paths::PathKind;
3434
use rustc_session::Session;
3535
use rustc_span::symbol::Symbol;
36-
use rustc_span::FileName;
36+
use rustc_span::{FileName, RealFileName};
3737
use rustc_trait_selection::traits;
3838
use rustc_typeck as typeck;
3939

@@ -569,13 +569,16 @@ fn write_out_deps(
569569
for cnum in resolver.cstore().crates_untracked() {
570570
let source = resolver.cstore().crate_source_untracked(cnum);
571571
if let Some((path, _)) = source.dylib {
572-
files.push(escape_dep_filename(&FileName::Real(path)));
572+
let file_name = FileName::Real(RealFileName::Named(path));
573+
files.push(escape_dep_filename(&file_name));
573574
}
574575
if let Some((path, _)) = source.rlib {
575-
files.push(escape_dep_filename(&FileName::Real(path)));
576+
let file_name = FileName::Real(RealFileName::Named(path));
577+
files.push(escape_dep_filename(&file_name));
576578
}
577579
if let Some((path, _)) = source.rmeta {
578-
files.push(escape_dep_filename(&FileName::Real(path)));
580+
let file_name = FileName::Real(RealFileName::Named(path));
581+
files.push(escape_dep_filename(&file_name));
579582
}
580583
}
581584
});

src/librustc_metadata/rmeta/decoder.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -1471,15 +1471,22 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
14711471

14721472
if let Some(virtual_dir) = virtual_rust_source_base_dir {
14731473
if let Some(real_dir) = &sess.real_rust_source_base_dir {
1474-
if let rustc_span::FileName::Real(path) = name {
1475-
if let Ok(rest) = path.strip_prefix(virtual_dir) {
1476-
let new_path = real_dir.join(rest);
1477-
debug!(
1478-
"try_to_translate_virtual_to_real: `{}` -> `{}`",
1479-
path.display(),
1480-
new_path.display(),
1481-
);
1482-
*path = new_path;
1474+
if let rustc_span::FileName::Real(old_name) = name {
1475+
if let rustc_span::RealFileName::Named(one_path) = old_name {
1476+
if let Ok(rest) = one_path.strip_prefix(virtual_dir) {
1477+
let virtual_name = one_path.clone();
1478+
let new_path = real_dir.join(rest);
1479+
debug!(
1480+
"try_to_translate_virtual_to_real: `{}` -> `{}`",
1481+
virtual_name.display(),
1482+
new_path.display(),
1483+
);
1484+
let new_name = rustc_span::RealFileName::Devirtualized {
1485+
local_path: new_path,
1486+
virtual_name,
1487+
};
1488+
*old_name = new_name;
1489+
}
14831490
}
14841491
}
14851492
}

src/librustc_metadata/rmeta/encoder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ impl<'tcx> EncodeContext<'tcx> {
396396
// any relative paths are potentially relative to a
397397
// wrong directory.
398398
FileName::Real(ref name) => {
399+
let name = name.local_path();
399400
let mut adapted = (**source_file).clone();
400401
adapted.name = Path::new(&working_dir).join(name).into();
401402
adapted.name_hash = {

src/librustc_save_analysis/span_utils.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ impl<'a> SpanUtils<'a> {
1616

1717
pub fn make_filename_string(&self, file: &SourceFile) -> String {
1818
match &file.name {
19-
FileName::Real(path) if !file.name_was_remapped => {
19+
FileName::Real(name) if !file.name_was_remapped => {
20+
let path = name.local_path();
2021
if path.is_absolute() {
2122
self.sess
2223
.source_map()
2324
.path_mapping()
24-
.map_prefix(path.clone())
25+
.map_prefix(path.into())
2526
.0
2627
.display()
2728
.to_string()

src/librustc_span/lib.rs

+44-4
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use std::cmp::{self, Ordering};
5353
use std::fmt;
5454
use std::hash::Hash;
5555
use std::ops::{Add, Sub};
56-
use std::path::PathBuf;
56+
use std::path::{Path, PathBuf};
5757
use std::str::FromStr;
5858

5959
use md5::Md5;
@@ -81,11 +81,45 @@ impl Globals {
8181

8282
scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
8383

84+
/// FIXME: Perhaps this should not implement Rustc{Decodable, Encodable}
85+
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
86+
#[derive(HashStable_Generic)]
87+
pub enum RealFileName {
88+
Named(PathBuf),
89+
/// For de-virtualized paths (namely paths into libstd that have been mapped
90+
/// to the appropriate spot on the local host's file system),
91+
Devirtualized {
92+
/// `local_path` is the (host-dependent) local path to the file.
93+
local_path: PathBuf,
94+
/// `virtual_name` is the stable path rustc will store internally within
95+
/// build artifacts.
96+
virtual_name: PathBuf,
97+
},
98+
}
99+
100+
impl RealFileName {
101+
/// Returns the path suitable for reading from the file system on the local host.
102+
pub fn local_path(&self) -> &Path {
103+
match self {
104+
RealFileName::Named(p)
105+
| RealFileName::Devirtualized { local_path: p, virtual_name: _ } => &p,
106+
}
107+
}
108+
109+
/// Returns the path suitable for reading from the file system on the local host.
110+
pub fn into_local_path(self) -> PathBuf {
111+
match self {
112+
RealFileName::Named(p)
113+
| RealFileName::Devirtualized { local_path: p, virtual_name: _ } => p,
114+
}
115+
}
116+
}
117+
84118
/// Differentiates between real files and common virtual files.
85119
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
86120
#[derive(HashStable_Generic)]
87121
pub enum FileName {
88-
Real(PathBuf),
122+
Real(RealFileName),
89123
/// Call to `quote!`.
90124
QuoteExpansion(u64),
91125
/// Command line.
@@ -107,7 +141,13 @@ impl std::fmt::Display for FileName {
107141
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108142
use FileName::*;
109143
match *self {
110-
Real(ref path) => write!(fmt, "{}", path.display()),
144+
Real(RealFileName::Named(ref path)) => write!(fmt, "{}", path.display()),
145+
// FIXME: might be nice to display both compoments of Devirtualized.
146+
// But for now (to backport fix for issue #70924), best to not
147+
// perturb diagnostics so its obvious test suite still works.
148+
Real(RealFileName::Devirtualized { ref local_path, virtual_name: _ }) => {
149+
write!(fmt, "{}", local_path.display())
150+
}
111151
QuoteExpansion(_) => write!(fmt, "<quote expansion>"),
112152
MacroExpansion(_) => write!(fmt, "<macro expansion>"),
113153
Anon(_) => write!(fmt, "<anon>"),
@@ -123,7 +163,7 @@ impl std::fmt::Display for FileName {
123163
impl From<PathBuf> for FileName {
124164
fn from(p: PathBuf) -> Self {
125165
assert!(!p.to_string_lossy().ends_with('>'));
126-
FileName::Real(p)
166+
FileName::Real(RealFileName::Named(p))
127167
}
128168
}
129169

src/librustc_span/source_map.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ impl SourceMap {
235235

236236
fn try_new_source_file(
237237
&self,
238-
filename: FileName,
238+
mut filename: FileName,
239239
src: String,
240240
) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
241241
// The path is used to determine the directory for loading submodules and
@@ -245,13 +245,22 @@ impl SourceMap {
245245
// be empty, so the working directory will be used.
246246
let unmapped_path = filename.clone();
247247

248-
let (filename, was_remapped) = match filename {
249-
FileName::Real(filename) => {
250-
let (filename, was_remapped) = self.path_mapping.map_prefix(filename);
251-
(FileName::Real(filename), was_remapped)
248+
let was_remapped;
249+
if let FileName::Real(real_filename) = &mut filename {
250+
match real_filename {
251+
RealFileName::Named(path_to_be_remapped)
252+
| RealFileName::Devirtualized {
253+
local_path: path_to_be_remapped,
254+
virtual_name: _,
255+
} => {
256+
let mapped = self.path_mapping.map_prefix(path_to_be_remapped.clone());
257+
was_remapped = mapped.1;
258+
*path_to_be_remapped = mapped.0;
259+
}
252260
}
253-
other => (other, false),
254-
};
261+
} else {
262+
was_remapped = false;
263+
}
255264

256265
let file_id =
257266
StableSourceFileId::new_from_pieces(&filename, was_remapped, Some(&unmapped_path));
@@ -998,7 +1007,7 @@ impl SourceMap {
9981007
}
9991008
pub fn ensure_source_file_source_present(&self, source_file: Lrc<SourceFile>) -> bool {
10001009
source_file.add_external_src(|| match source_file.name {
1001-
FileName::Real(ref name) => self.file_loader.read_file(name).ok(),
1010+
FileName::Real(ref name) => self.file_loader.read_file(name.local_path()).ok(),
10021011
_ => None,
10031012
})
10041013
}

src/librustdoc/html/render.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ pub fn run(
473473
} = options;
474474

475475
let src_root = match krate.src {
476-
FileName::Real(ref p) => match p.parent() {
476+
FileName::Real(ref p) => match p.local_path().parent() {
477477
Some(p) => p.to_path_buf(),
478478
None => PathBuf::new(),
479479
},
@@ -1621,9 +1621,10 @@ impl Context {
16211621

16221622
// We can safely ignore synthetic `SourceFile`s.
16231623
let file = match item.source.filename {
1624-
FileName::Real(ref path) => path,
1624+
FileName::Real(ref path) => path.local_path().to_path_buf(),
16251625
_ => return None,
16261626
};
1627+
let file = &file;
16271628

16281629
let (krate, path) = if item.source.cnum == LOCAL_CRATE {
16291630
if let Some(path) = self.shared.local_sources.get(file) {

src/librustdoc/html/render/cache.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl Cache {
173173
// Cache where all our extern crates are located
174174
for &(n, ref e) in &krate.externs {
175175
let src_root = match e.src {
176-
FileName::Real(ref p) => match p.parent() {
176+
FileName::Real(ref p) => match p.local_path().parent() {
177177
Some(p) => p.to_path_buf(),
178178
None => PathBuf::new(),
179179
},

src/librustdoc/html/sources.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ impl<'a> SourceCollector<'a> {
6767
/// Renders the given filename into its corresponding HTML source file.
6868
fn emit_source(&mut self, filename: &FileName) -> Result<(), Error> {
6969
let p = match *filename {
70-
FileName::Real(ref file) => file,
70+
FileName::Real(ref file) => file.local_path().to_path_buf(),
7171
_ => return Ok(()),
7272
};
73-
if self.scx.local_sources.contains_key(&**p) {
73+
if self.scx.local_sources.contains_key(&*p) {
7474
// We've already emitted this source
7575
return Ok(());
7676
}

src/librustdoc/test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ impl Collector {
688688
let filename = source_map.span_to_filename(self.position);
689689
if let FileName::Real(ref filename) = filename {
690690
if let Ok(cur_dir) = env::current_dir() {
691-
if let Ok(path) = filename.strip_prefix(&cur_dir) {
691+
if let Ok(path) = filename.local_path().strip_prefix(&cur_dir) {
692692
return path.to_owned().into();
693693
}
694694
}
@@ -718,7 +718,7 @@ impl Tester for Collector {
718718
// FIXME(#44940): if doctests ever support path remapping, then this filename
719719
// needs to be the result of `SourceMap::span_to_unmapped_path`.
720720
let path = match &filename {
721-
FileName::Real(path) => path.clone(),
721+
FileName::Real(path) => path.local_path().to_path_buf(),
722722
_ => PathBuf::from(r"doctest.rs"),
723723
};
724724

0 commit comments

Comments
 (0)