Skip to content

Commit 810d99e

Browse files
committed
Prepare rustc-dev component un-remapping in the compiler
1 parent 6c8138d commit 810d99e

File tree

3 files changed

+112
-82
lines changed

3 files changed

+112
-82
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 101 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Decoding metadata from a single crate's metadata
22

33
use std::iter::TrustedLen;
4-
use std::path::Path;
4+
use std::path::{Path, PathBuf};
55
use std::sync::{Arc, OnceLock};
66
use std::{io, iter, mem};
77

@@ -1610,10 +1610,14 @@ impl<'a> CrateMetadataRef<'a> {
16101610
/// Proc macro crates don't currently export spans, so this function does not have
16111611
/// to work for them.
16121612
fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1613-
fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
1613+
fn filter<'a>(
1614+
sess: &Session,
1615+
real_source_base_dir: &Option<PathBuf>,
1616+
path: Option<&'a Path>,
1617+
) -> Option<&'a Path> {
16141618
path.filter(|_| {
16151619
// Only spend time on further checks if we have what to translate *to*.
1616-
sess.opts.real_rust_source_base_dir.is_some()
1620+
real_source_base_dir.is_some()
16171621
// Some tests need the translation to be always skipped.
16181622
&& sess.opts.unstable_opts.translate_remapped_path_to_local_path
16191623
})
@@ -1625,57 +1629,92 @@ impl<'a> CrateMetadataRef<'a> {
16251629
})
16261630
}
16271631

1628-
let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
1629-
// Translate the virtual `/rustc/$hash` prefix back to a real directory
1630-
// that should hold actual sources, where possible.
1631-
//
1632-
// NOTE: if you update this, you might need to also update bootstrap's code for generating
1633-
// the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1634-
let virtual_rust_source_base_dir = [
1635-
filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)),
1636-
filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()),
1637-
];
1632+
let try_to_translate_virtual_to_real =
1633+
|virtual_source_base_dir: Option<&str>,
1634+
real_source_base_dir: &Option<PathBuf>,
1635+
name: &mut rustc_span::FileName| {
1636+
let virtual_source_base_dir = [
1637+
filter(sess, real_source_base_dir, virtual_source_base_dir.map(Path::new)),
1638+
filter(
1639+
sess,
1640+
real_source_base_dir,
1641+
sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref(),
1642+
),
1643+
];
16381644

1639-
debug!(
1640-
"try_to_translate_virtual_to_real(name={:?}): \
1641-
virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
1642-
name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
1643-
);
1645+
debug!(
1646+
"try_to_translate_virtual_to_real(name={:?}): \
1647+
virtual_source_base_dir={:?}, real_source_base_dir={:?}",
1648+
name, virtual_source_base_dir, real_source_base_dir,
1649+
);
1650+
1651+
for virtual_dir in virtual_source_base_dir.iter().flatten() {
1652+
if let Some(real_dir) = &real_source_base_dir
1653+
&& let rustc_span::FileName::Real(old_name) = name
1654+
&& let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1655+
old_name
1656+
&& let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
1657+
{
1658+
let new_path = real_dir.join(rest);
1659+
1660+
debug!(
1661+
"try_to_translate_virtual_to_real: `{}` -> `{}`",
1662+
virtual_name.display(),
1663+
new_path.display(),
1664+
);
1665+
1666+
// Check if the translated real path is affected by any user-requested
1667+
// remaps via --remap-path-prefix. Apply them if so.
1668+
// Note that this is a special case for imported rust-src paths specified by
1669+
// https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1670+
// Other imported paths are not currently remapped (see #66251).
1671+
let (user_remapped, applied) =
1672+
sess.source_map().path_mapping().map_prefix(&new_path);
1673+
let new_name = if applied {
1674+
rustc_span::RealFileName::Remapped {
1675+
local_path: Some(new_path.clone()),
1676+
virtual_name: user_remapped.to_path_buf(),
1677+
}
1678+
} else {
1679+
rustc_span::RealFileName::LocalPath(new_path)
1680+
};
1681+
*old_name = new_name;
1682+
}
1683+
}
1684+
};
16441685

1645-
for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
1646-
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1686+
let try_to_translate_real_to_virtual =
1687+
|virtual_source_base_dir: Option<&str>,
1688+
real_source_base_dir: &Option<PathBuf>,
1689+
subdir: &str,
1690+
name: &mut rustc_span::FileName| {
1691+
if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1692+
&& let Some(real_dir) = real_source_base_dir
16471693
&& let rustc_span::FileName::Real(old_name) = name
1648-
&& let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1649-
old_name
1650-
&& let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
16511694
{
1652-
let new_path = real_dir.join(rest);
1653-
1654-
debug!(
1655-
"try_to_translate_virtual_to_real: `{}` -> `{}`",
1656-
virtual_name.display(),
1657-
new_path.display(),
1658-
);
1659-
1660-
// Check if the translated real path is affected by any user-requested
1661-
// remaps via --remap-path-prefix. Apply them if so.
1662-
// Note that this is a special case for imported rust-src paths specified by
1663-
// https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1664-
// Other imported paths are not currently remapped (see #66251).
1665-
let (user_remapped, applied) =
1666-
sess.source_map().path_mapping().map_prefix(&new_path);
1667-
let new_name = if applied {
1668-
rustc_span::RealFileName::Remapped {
1669-
local_path: Some(new_path.clone()),
1670-
virtual_name: user_remapped.to_path_buf(),
1695+
let relative_path = match old_name {
1696+
rustc_span::RealFileName::LocalPath(local) => {
1697+
local.strip_prefix(real_dir).ok()
1698+
}
1699+
rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1700+
virtual_source_base_dir
1701+
.and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
16711702
}
1672-
} else {
1673-
rustc_span::RealFileName::LocalPath(new_path)
16741703
};
1675-
*old_name = new_name;
1704+
debug!(
1705+
?relative_path,
1706+
?virtual_dir,
1707+
?subdir,
1708+
"simulate_remapped_rust_src_base"
1709+
);
1710+
if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
1711+
*old_name = rustc_span::RealFileName::Remapped {
1712+
local_path: None,
1713+
virtual_name: virtual_dir.join(subdir).join(rest),
1714+
};
1715+
}
16761716
}
1677-
}
1678-
};
1717+
};
16791718

16801719
let mut import_info = self.cdata.source_map_import_info.lock();
16811720
for _ in import_info.len()..=(source_file_index as usize) {
@@ -1713,36 +1752,23 @@ impl<'a> CrateMetadataRef<'a> {
17131752
// This is useful for testing so that tests about the effects of
17141753
// `try_to_translate_virtual_to_real` don't have to worry about how the
17151754
// compiler is bootstrapped.
1716-
if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1717-
&& let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1718-
&& let rustc_span::FileName::Real(ref mut old_name) = name
1719-
{
1720-
let relative_path = match old_name {
1721-
rustc_span::RealFileName::LocalPath(local) => {
1722-
local.strip_prefix(real_dir).ok()
1723-
}
1724-
rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1725-
option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR")
1726-
.and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
1727-
}
1728-
};
1729-
debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
1730-
for subdir in ["library", "compiler"] {
1731-
if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok())
1732-
{
1733-
*old_name = rustc_span::RealFileName::Remapped {
1734-
local_path: None, // FIXME: maybe we should preserve this?
1735-
virtual_name: virtual_dir.join(subdir).join(rest),
1736-
};
1737-
break;
1738-
}
1739-
}
1740-
}
1755+
try_to_translate_real_to_virtual(
1756+
option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1757+
&sess.opts.real_rust_source_base_dir,
1758+
"library",
1759+
&mut name,
1760+
);
17411761

17421762
// If this file's path has been remapped to `/rustc/$hash`,
1743-
// we might be able to reverse that (also see comments above,
1744-
// on `try_to_translate_virtual_to_real`).
1745-
try_to_translate_virtual_to_real(&mut name);
1763+
// we might be able to reverse that.
1764+
//
1765+
// NOTE: if you update this, you might need to also update bootstrap's code for generating
1766+
// the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1767+
try_to_translate_virtual_to_real(
1768+
option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1769+
&sess.opts.real_rust_source_base_dir,
1770+
&mut name,
1771+
);
17461772

17471773
let local_version = sess.source_map().new_imported_source_file(
17481774
name,

compiler/rustc_session/src/config.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,9 +2692,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26922692

26932693
let sysroot = filesearch::materialize_sysroot(sysroot_opt);
26942694

2695-
let real_rust_source_base_dir = {
2696-
// This is the location used by the `rust-src` `rustup` component.
2697-
let mut candidate = sysroot.join("lib/rustlib/src/rust");
2695+
let real_source_base_dir = |suffix: &str, confirm: &str| {
2696+
let mut candidate = sysroot.join(suffix);
26982697
if let Ok(metadata) = candidate.symlink_metadata() {
26992698
// Replace the symlink bootstrap creates, with its destination.
27002699
// We could try to use `fs::canonicalize` instead, but that might
@@ -2707,9 +2706,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27072706
}
27082707

27092708
// Only use this directory if it has a file we can expect to always find.
2710-
candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
2709+
candidate.join(confirm).is_file().then_some(candidate)
27112710
};
27122711

2712+
let real_rust_source_base_dir =
2713+
// This is the location used by the `rust-src` `rustup` component.
2714+
real_source_base_dir("lib/rustlib/src/rust", "library/std/src/lib.rs");
2715+
27132716
let mut search_paths = vec![];
27142717
for s in &matches.opt_strs("L") {
27152718
search_paths.push(SearchPath::from_cli_opt(

compiler/rustc_session/src/options.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,10 @@ top_level_options!(
387387

388388
/// Remap source path prefixes in all output (messages, object files, debug, etc.).
389389
remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
390-
/// Base directory containing the `src/` for the Rust standard library, and
391-
/// potentially `rustc` as well, if we can find it. Right now it's always
392-
/// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
390+
391+
/// Base directory containing the `library/` directory for the Rust standard library.
392+
/// Right now it's always `$sysroot/lib/rustlib/src/rust`
393+
/// (i.e. the `rustup` `rust-src` component).
393394
///
394395
/// This directory is what the virtual `/rustc/$hash` is translated back to,
395396
/// if Rust was built with path remapping to `/rustc/$hash` enabled

0 commit comments

Comments
 (0)