Skip to content

Commit 0a91077

Browse files
pnkfelixMark-Simulacrum
authored andcommitted
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 9912484 commit 0a91077

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
@@ -1086,7 +1086,7 @@ impl<'a> ExtCtxt<'a> {
10861086
if !path.is_absolute() {
10871087
let callsite = span.source_callsite();
10881088
let mut result = match self.source_map().span_to_unmapped_path(callsite) {
1089-
FileName::Real(path) => path,
1089+
FileName::Real(name) => name.into_local_path(),
10901090
FileName::DocTest(path, _) => path,
10911091
other => {
10921092
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
@@ -596,7 +596,8 @@ impl server::SourceFile for Rustc<'_> {
596596
}
597597
fn path(&mut self, file: &Self::SourceFile) -> String {
598598
match file.name {
599-
FileName::Real(ref path) => path
599+
FileName::Real(ref name) => name
600+
.local_path()
600601
.to_str()
601602
.expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
602603
.to_string(),

src/librustc_interface/passes.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_session::output::{filename_for_input, filename_for_metadata};
3535
use rustc_session::search_paths::PathKind;
3636
use rustc_session::Session;
3737
use rustc_span::symbol::Symbol;
38-
use rustc_span::FileName;
38+
use rustc_span::{FileName, RealFileName};
3939
use rustc_trait_selection::traits;
4040
use rustc_typeck as typeck;
4141

@@ -570,13 +570,16 @@ fn write_out_deps(
570570
for cnum in resolver.cstore().crates_untracked() {
571571
let source = resolver.cstore().crate_source_untracked(cnum);
572572
if let Some((path, _)) = source.dylib {
573-
files.push(escape_dep_filename(&FileName::Real(path)));
573+
let file_name = FileName::Real(RealFileName::Named(path));
574+
files.push(escape_dep_filename(&file_name));
574575
}
575576
if let Some((path, _)) = source.rlib {
576-
files.push(escape_dep_filename(&FileName::Real(path)));
577+
let file_name = FileName::Real(RealFileName::Named(path));
578+
files.push(escape_dep_filename(&file_name));
577579
}
578580
if let Some((path, _)) = source.rmeta {
579-
files.push(escape_dep_filename(&FileName::Real(path)));
581+
let file_name = FileName::Real(RealFileName::Named(path));
582+
files.push(escape_dep_filename(&file_name));
580583
}
581584
}
582585
});

src/librustc_metadata/rmeta/decoder.rs

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

14861486
if let Some(virtual_dir) = virtual_rust_source_base_dir {
14871487
if let Some(real_dir) = &sess.real_rust_source_base_dir {
1488-
if let rustc_span::FileName::Real(path) = name {
1489-
if let Ok(rest) = path.strip_prefix(virtual_dir) {
1490-
let new_path = real_dir.join(rest);
1491-
debug!(
1492-
"try_to_translate_virtual_to_real: `{}` -> `{}`",
1493-
path.display(),
1494-
new_path.display(),
1495-
);
1496-
*path = new_path;
1488+
if let rustc_span::FileName::Real(old_name) = name {
1489+
if let rustc_span::RealFileName::Named(one_path) = old_name {
1490+
if let Ok(rest) = one_path.strip_prefix(virtual_dir) {
1491+
let virtual_name = one_path.clone();
1492+
let new_path = real_dir.join(rest);
1493+
debug!(
1494+
"try_to_translate_virtual_to_real: `{}` -> `{}`",
1495+
virtual_name.display(),
1496+
new_path.display(),
1497+
);
1498+
let new_name = rustc_span::RealFileName::Devirtualized {
1499+
local_path: new_path,
1500+
virtual_name,
1501+
};
1502+
*old_name = new_name;
1503+
}
14971504
}
14981505
}
14991506
}

src/librustc_metadata/rmeta/encoder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ impl<'tcx> EncodeContext<'tcx> {
398398
// any relative paths are potentially relative to a
399399
// wrong directory.
400400
FileName::Real(ref name) => {
401+
let name = name.local_path();
401402
let mut adapted = (**source_file).clone();
402403
adapted.name = Path::new(&working_dir).join(name).into();
403404
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
@@ -49,7 +49,7 @@ use std::cmp::{self, Ordering};
4949
use std::fmt;
5050
use std::hash::Hash;
5151
use std::ops::{Add, Sub};
52-
use std::path::PathBuf;
52+
use std::path::{Path, PathBuf};
5353
use std::str::FromStr;
5454

5555
use md5::Md5;
@@ -77,11 +77,45 @@ impl Globals {
7777

7878
scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
7979

80+
/// FIXME: Perhaps this should not implement Rustc{Decodable, Encodable}
81+
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
82+
#[derive(HashStable_Generic)]
83+
pub enum RealFileName {
84+
Named(PathBuf),
85+
/// For de-virtualized paths (namely paths into libstd that have been mapped
86+
/// to the appropriate spot on the local host's file system),
87+
Devirtualized {
88+
/// `local_path` is the (host-dependent) local path to the file.
89+
local_path: PathBuf,
90+
/// `virtual_name` is the stable path rustc will store internally within
91+
/// build artifacts.
92+
virtual_name: PathBuf,
93+
},
94+
}
95+
96+
impl RealFileName {
97+
/// Returns the path suitable for reading from the file system on the local host.
98+
pub fn local_path(&self) -> &Path {
99+
match self {
100+
RealFileName::Named(p)
101+
| RealFileName::Devirtualized { local_path: p, virtual_name: _ } => &p,
102+
}
103+
}
104+
105+
/// Returns the path suitable for reading from the file system on the local host.
106+
pub fn into_local_path(self) -> PathBuf {
107+
match self {
108+
RealFileName::Named(p)
109+
| RealFileName::Devirtualized { local_path: p, virtual_name: _ } => p,
110+
}
111+
}
112+
}
113+
80114
/// Differentiates between real files and common virtual files.
81115
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
82116
#[derive(HashStable_Generic)]
83117
pub enum FileName {
84-
Real(PathBuf),
118+
Real(RealFileName),
85119
/// Call to `quote!`.
86120
QuoteExpansion(u64),
87121
/// Command line.
@@ -103,7 +137,13 @@ impl std::fmt::Display for FileName {
103137
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104138
use FileName::*;
105139
match *self {
106-
Real(ref path) => write!(fmt, "{}", path.display()),
140+
Real(RealFileName::Named(ref path)) => write!(fmt, "{}", path.display()),
141+
// FIXME: might be nice to display both compoments of Devirtualized.
142+
// But for now (to backport fix for issue #70924), best to not
143+
// perturb diagnostics so its obvious test suite still works.
144+
Real(RealFileName::Devirtualized { ref local_path, virtual_name: _ }) => {
145+
write!(fmt, "{}", local_path.display())
146+
}
107147
QuoteExpansion(_) => write!(fmt, "<quote expansion>"),
108148
MacroExpansion(_) => write!(fmt, "<macro expansion>"),
109149
Anon(_) => write!(fmt, "<anon>"),
@@ -119,7 +159,7 @@ impl std::fmt::Display for FileName {
119159
impl From<PathBuf> for FileName {
120160
fn from(p: PathBuf) -> Self {
121161
assert!(!p.to_string_lossy().ends_with('>'));
122-
FileName::Real(p)
162+
FileName::Real(RealFileName::Named(p))
123163
}
124164
}
125165

src/librustc_span/source_map.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ impl SourceMap {
247247

248248
fn try_new_source_file(
249249
&self,
250-
filename: FileName,
250+
mut filename: FileName,
251251
src: String,
252252
) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
253253
// The path is used to determine the directory for loading submodules and
@@ -257,13 +257,22 @@ impl SourceMap {
257257
// be empty, so the working directory will be used.
258258
let unmapped_path = filename.clone();
259259

260-
let (filename, was_remapped) = match filename {
261-
FileName::Real(filename) => {
262-
let (filename, was_remapped) = self.path_mapping.map_prefix(filename);
263-
(FileName::Real(filename), was_remapped)
260+
let was_remapped;
261+
if let FileName::Real(real_filename) = &mut filename {
262+
match real_filename {
263+
RealFileName::Named(path_to_be_remapped)
264+
| RealFileName::Devirtualized {
265+
local_path: path_to_be_remapped,
266+
virtual_name: _,
267+
} => {
268+
let mapped = self.path_mapping.map_prefix(path_to_be_remapped.clone());
269+
was_remapped = mapped.1;
270+
*path_to_be_remapped = mapped.0;
271+
}
264272
}
265-
other => (other, false),
266-
};
273+
} else {
274+
was_remapped = false;
275+
}
267276

268277
let file_id =
269278
StableSourceFileId::new_from_pieces(&filename, was_remapped, Some(&unmapped_path));
@@ -1001,7 +1010,7 @@ impl SourceMap {
10011010
}
10021011
pub fn ensure_source_file_source_present(&self, source_file: Lrc<SourceFile>) -> bool {
10031012
source_file.add_external_src(|| match source_file.name {
1004-
FileName::Real(ref name) => self.file_loader.read_file(name).ok(),
1013+
FileName::Real(ref name) => self.file_loader.read_file(name.local_path()).ok(),
10051014
_ => None,
10061015
})
10071016
}

src/librustdoc/html/render.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ pub fn run(
465465
} = options;
466466

467467
let src_root = match krate.src {
468-
FileName::Real(ref p) => match p.parent() {
468+
FileName::Real(ref p) => match p.local_path().parent() {
469469
Some(p) => p.to_path_buf(),
470470
None => PathBuf::new(),
471471
},
@@ -1650,9 +1650,10 @@ impl Context {
16501650

16511651
// We can safely ignore synthetic `SourceFile`s.
16521652
let file = match item.source.filename {
1653-
FileName::Real(ref path) => path,
1653+
FileName::Real(ref path) => path.local_path().to_path_buf(),
16541654
_ => return None,
16551655
};
1656+
let file = &file;
16561657

16571658
let (krate, path) = if item.source.cnum == LOCAL_CRATE {
16581659
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
@@ -663,7 +663,7 @@ impl Collector {
663663
let filename = source_map.span_to_filename(self.position);
664664
if let FileName::Real(ref filename) = filename {
665665
if let Ok(cur_dir) = env::current_dir() {
666-
if let Ok(path) = filename.strip_prefix(&cur_dir) {
666+
if let Ok(path) = filename.local_path().strip_prefix(&cur_dir) {
667667
return path.to_owned().into();
668668
}
669669
}
@@ -693,7 +693,7 @@ impl Tester for Collector {
693693
// FIXME(#44940): if doctests ever support path remapping, then this filename
694694
// needs to be the result of `SourceMap::span_to_unmapped_path`.
695695
let path = match &filename {
696-
FileName::Real(path) => path.clone(),
696+
FileName::Real(path) => path.local_path().to_path_buf(),
697697
_ => PathBuf::from(r"doctest.rs"),
698698
};
699699

0 commit comments

Comments
 (0)