Rollup merge of #139550 - Urgau:rmeta-remap-path-scope, r=nnethercote
Fix `-Zremap-path-scope` rmeta handling This PR fixes the conditional remapping (`-Zremap-path-scope`) of rmeta file paths ~~by using the `debuginfo` scope~~ by conditionally embedding the local path in addition to the remapped path. Fixes https://github.com/rust-lang/rust/issues/139217
This commit is contained in:
@@ -551,8 +551,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
match source_file.name {
|
||||
FileName::Real(ref original_file_name) => {
|
||||
// FIXME: This should probably to conditionally remapped under
|
||||
// a RemapPathScopeComponents but which one?
|
||||
let adapted_file_name = source_map
|
||||
.path_mapping()
|
||||
.to_embeddable_absolute_path(original_file_name.clone(), working_directory);
|
||||
|
||||
@@ -24,7 +24,8 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
|
||||
use rustc_span::source_map::FilePathMapping;
|
||||
use rustc_span::{
|
||||
FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm, Symbol, sym,
|
||||
FileName, FileNameDisplayPreference, FileNameEmbeddablePreference, RealFileName,
|
||||
SourceFileHashAlgorithm, Symbol, sym,
|
||||
};
|
||||
use rustc_target::spec::{
|
||||
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTuple,
|
||||
@@ -1320,6 +1321,11 @@ fn file_path_mapping(
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
},
|
||||
if unstable_opts.remap_path_scope.is_all() {
|
||||
FileNameEmbeddablePreference::RemappedOnly
|
||||
} else {
|
||||
FileNameEmbeddablePreference::LocalAndRemapped
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ pub fn with_metavar_spans<R>(f: impl FnOnce(&MetavarSpansMap) -> R) -> R {
|
||||
|
||||
// FIXME: We should use this enum or something like it to get rid of the
|
||||
// use of magic `/rust/1.x/...` paths across the board.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable)]
|
||||
pub enum RealFileName {
|
||||
LocalPath(PathBuf),
|
||||
/// For remapped paths (namely paths into libstd that have been mapped
|
||||
@@ -250,28 +250,6 @@ impl Hash for RealFileName {
|
||||
}
|
||||
}
|
||||
|
||||
// This is functionally identical to #[derive(Encodable)], with the exception of
|
||||
// an added assert statement
|
||||
impl<S: Encoder> Encodable<S> for RealFileName {
|
||||
fn encode(&self, encoder: &mut S) {
|
||||
match *self {
|
||||
RealFileName::LocalPath(ref local_path) => {
|
||||
encoder.emit_u8(0);
|
||||
local_path.encode(encoder);
|
||||
}
|
||||
|
||||
RealFileName::Remapped { ref local_path, ref virtual_name } => {
|
||||
encoder.emit_u8(1);
|
||||
// For privacy and build reproducibility, we must not embed host-dependant path
|
||||
// in artifacts if they have been remapped by --remap-path-prefix
|
||||
assert!(local_path.is_none());
|
||||
local_path.encode(encoder);
|
||||
virtual_name.encode(encoder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RealFileName {
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
@@ -368,6 +346,16 @@ impl From<PathBuf> for FileName {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum FileNameEmbeddablePreference {
|
||||
/// If a remapped path is available, only embed the `virtual_path` and omit the `local_path`.
|
||||
///
|
||||
/// Otherwise embed the local-path into the `virtual_path`.
|
||||
RemappedOnly,
|
||||
/// Embed the original path as well as its remapped `virtual_path` component if available.
|
||||
LocalAndRemapped,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum FileNameDisplayPreference {
|
||||
/// Display the path after the application of rewrite rules provided via `--remap-path-prefix`.
|
||||
|
||||
@@ -1108,18 +1108,28 @@ pub fn get_source_map() -> Option<Arc<SourceMap>> {
|
||||
pub struct FilePathMapping {
|
||||
mapping: Vec<(PathBuf, PathBuf)>,
|
||||
filename_display_for_diagnostics: FileNameDisplayPreference,
|
||||
filename_embeddable_preference: FileNameEmbeddablePreference,
|
||||
}
|
||||
|
||||
impl FilePathMapping {
|
||||
pub fn empty() -> FilePathMapping {
|
||||
FilePathMapping::new(Vec::new(), FileNameDisplayPreference::Local)
|
||||
FilePathMapping::new(
|
||||
Vec::new(),
|
||||
FileNameDisplayPreference::Local,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
mapping: Vec<(PathBuf, PathBuf)>,
|
||||
filename_display_for_diagnostics: FileNameDisplayPreference,
|
||||
filename_embeddable_preference: FileNameEmbeddablePreference,
|
||||
) -> FilePathMapping {
|
||||
FilePathMapping { mapping, filename_display_for_diagnostics }
|
||||
FilePathMapping {
|
||||
mapping,
|
||||
filename_display_for_diagnostics,
|
||||
filename_embeddable_preference,
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies any path prefix substitution as defined by the mapping.
|
||||
@@ -1217,11 +1227,13 @@ impl FilePathMapping {
|
||||
) -> RealFileName {
|
||||
match file_path {
|
||||
// Anything that's already remapped we don't modify, except for erasing
|
||||
// the `local_path` portion.
|
||||
RealFileName::Remapped { local_path: _, virtual_name } => {
|
||||
// the `local_path` portion (if desired).
|
||||
RealFileName::Remapped { local_path, virtual_name } => {
|
||||
RealFileName::Remapped {
|
||||
// We do not want any local path to be exported into metadata
|
||||
local_path: None,
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => local_path,
|
||||
},
|
||||
// We use the remapped name verbatim, even if it looks like a relative
|
||||
// path. The assumption is that the user doesn't want us to further
|
||||
// process paths that have gone through remapping.
|
||||
@@ -1231,12 +1243,18 @@ impl FilePathMapping {
|
||||
|
||||
RealFileName::LocalPath(unmapped_file_path) => {
|
||||
// If no remapping has been applied yet, try to do so
|
||||
let (new_path, was_remapped) = self.map_prefix(unmapped_file_path);
|
||||
let (new_path, was_remapped) = self.map_prefix(&unmapped_file_path);
|
||||
if was_remapped {
|
||||
// It was remapped, so don't modify further
|
||||
return RealFileName::Remapped {
|
||||
local_path: None,
|
||||
virtual_name: new_path.into_owned(),
|
||||
// But still provide the local path if desired
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => {
|
||||
Some(unmapped_file_path)
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1252,17 +1270,23 @@ impl FilePathMapping {
|
||||
|
||||
match working_directory {
|
||||
RealFileName::LocalPath(unmapped_working_dir_abs) => {
|
||||
let file_path_abs = unmapped_working_dir_abs.join(unmapped_file_path_rel);
|
||||
let unmapped_file_path_abs =
|
||||
unmapped_working_dir_abs.join(unmapped_file_path_rel);
|
||||
|
||||
// Although neither `working_directory` nor the file name were subject
|
||||
// to path remapping, the concatenation between the two may be. Hence
|
||||
// we need to do a remapping here.
|
||||
let (file_path_abs, was_remapped) = self.map_prefix(file_path_abs);
|
||||
let (file_path_abs, was_remapped) =
|
||||
self.map_prefix(&unmapped_file_path_abs);
|
||||
if was_remapped {
|
||||
RealFileName::Remapped {
|
||||
// Erase the actual path
|
||||
local_path: None,
|
||||
virtual_name: file_path_abs.into_owned(),
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => {
|
||||
Some(unmapped_file_path_abs)
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// No kind of remapping applied to this path, so
|
||||
@@ -1271,15 +1295,20 @@ impl FilePathMapping {
|
||||
}
|
||||
}
|
||||
RealFileName::Remapped {
|
||||
local_path: _,
|
||||
local_path,
|
||||
virtual_name: remapped_working_dir_abs,
|
||||
} => {
|
||||
// If working_directory has been remapped, then we emit
|
||||
// Remapped variant as the expanded path won't be valid
|
||||
RealFileName::Remapped {
|
||||
local_path: None,
|
||||
virtual_name: Path::new(remapped_working_dir_abs)
|
||||
.join(unmapped_file_path_rel),
|
||||
.join(&unmapped_file_path_rel),
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => local_path
|
||||
.as_ref()
|
||||
.map(|local_path| local_path.join(unmapped_file_path_rel)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1287,27 +1316,6 @@ impl FilePathMapping {
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand a relative path to an absolute path **without** remapping taken into account.
|
||||
///
|
||||
/// The resulting `RealFileName` will have its `virtual_path` portion erased if
|
||||
/// possible (i.e. if there's also a remapped path).
|
||||
pub fn to_local_embeddable_absolute_path(
|
||||
&self,
|
||||
file_path: RealFileName,
|
||||
working_directory: &RealFileName,
|
||||
) -> RealFileName {
|
||||
let file_path = file_path.local_path_if_available();
|
||||
if file_path.is_absolute() {
|
||||
// No remapping has applied to this path and it is absolute,
|
||||
// so the working directory cannot influence it either, so
|
||||
// we are done.
|
||||
return RealFileName::LocalPath(file_path.to_path_buf());
|
||||
}
|
||||
debug_assert!(file_path.is_relative());
|
||||
let working_directory = working_directory.local_path_if_available();
|
||||
RealFileName::LocalPath(Path::new(working_directory).join(file_path))
|
||||
}
|
||||
|
||||
/// Attempts to (heuristically) reverse a prefix mapping.
|
||||
///
|
||||
/// Returns [`Some`] if there is exactly one mapping where the "to" part is
|
||||
|
||||
@@ -305,6 +305,7 @@ fn path_prefix_remapping() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc/def"), path("foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("foo/src/main.rs"));
|
||||
@@ -316,6 +317,7 @@ fn path_prefix_remapping() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc/def"), path("/foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
|
||||
@@ -327,6 +329,7 @@ fn path_prefix_remapping() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/abc/def"), path("foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("foo/src/main.rs"));
|
||||
@@ -338,6 +341,7 @@ fn path_prefix_remapping() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/abc/def"), path("/foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
|
||||
@@ -351,6 +355,7 @@ fn path_prefix_remapping_expand_to_absolute() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
let working_directory = path("/foo");
|
||||
let working_directory = RealFileName::Remapped {
|
||||
@@ -448,6 +453,71 @@ fn path_prefix_remapping_expand_to_absolute() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_prefix_remapping_expand_to_absolute_and_local() {
|
||||
// "virtual" working directory is relative path
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped,
|
||||
);
|
||||
let working_directory = path("/foo");
|
||||
let working_directory = RealFileName::Remapped {
|
||||
local_path: Some(working_directory.clone()),
|
||||
virtual_name: mapping.map_prefix(working_directory).0.into_owned(),
|
||||
};
|
||||
|
||||
assert_eq!(working_directory.remapped_path_if_available(), path("FOO"));
|
||||
|
||||
// Unmapped absolute path
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("/foo/src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/foo/src/main.rs")),
|
||||
virtual_name: path("FOO/src/main.rs")
|
||||
}
|
||||
);
|
||||
|
||||
// Unmapped absolute path with unrelated working directory
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("/bar/src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/bar/src/main.rs")),
|
||||
virtual_name: path("BAR/src/main.rs")
|
||||
}
|
||||
);
|
||||
|
||||
// Already remapped absolute path, with unrelated working directory
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/bar/src/main.rs")),
|
||||
virtual_name: path("BAR/src/main.rs"),
|
||||
},
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/bar/src/main.rs")),
|
||||
virtual_name: path("BAR/src/main.rs")
|
||||
}
|
||||
);
|
||||
|
||||
// Already remapped relative path
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") },
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_prefix_remapping_reverse() {
|
||||
// Ignores options without alphanumeric chars.
|
||||
@@ -455,6 +525,7 @@ fn path_prefix_remapping_reverse() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/")), (path("def"), path("."))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
|
||||
assert_eq!(reverse_map_prefix(mapping, "/hello.rs"), None);
|
||||
@@ -466,6 +537,7 @@ fn path_prefix_remapping_reverse() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/redacted")), (path("def"), path("/redacted"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
|
||||
assert_eq!(reverse_map_prefix(mapping, "/redacted/hello.rs"), None);
|
||||
@@ -476,6 +548,7 @@ fn path_prefix_remapping_reverse() {
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/redacted")), (path("def/ghi"), path("/fake/dir"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
||||
@@ -91,6 +91,59 @@ fn main() {
|
||||
)),
|
||||
dwarf_test: DwarfDump::ParentTest,
|
||||
});
|
||||
|
||||
check_dwarf_deps("macro", DwarfDump::AvoidSrcPath);
|
||||
check_dwarf_deps("diagnostics", DwarfDump::AvoidSrcPath);
|
||||
check_dwarf_deps("macro,diagnostics", DwarfDump::AvoidSrcPath);
|
||||
check_dwarf_deps("object", DwarfDump::ContainsSrcPath);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn check_dwarf_deps(scope: &str, dwarf_test: DwarfDump) {
|
||||
// build some_value.rs
|
||||
let mut rustc_sm = rustc();
|
||||
rustc_sm.input(cwd().join("src/some_value.rs"));
|
||||
rustc_sm.arg("-Cdebuginfo=2");
|
||||
rustc_sm.arg(format!("-Zremap-path-scope={}", scope));
|
||||
rustc_sm.arg("--remap-path-prefix");
|
||||
rustc_sm.arg(format!("{}=/REMAPPED", cwd().display()));
|
||||
rustc_sm.arg("-Csplit-debuginfo=off");
|
||||
rustc_sm.run();
|
||||
|
||||
// build print_value.rs
|
||||
let print_value_rlib = rust_lib_name(&format!("print_value.{scope}"));
|
||||
let mut rustc_pv = rustc();
|
||||
rustc_pv.input(cwd().join("src/print_value.rs"));
|
||||
rustc_pv.output(&print_value_rlib);
|
||||
rustc_pv.arg("-Cdebuginfo=2");
|
||||
rustc_pv.arg(format!("-Zremap-path-scope={}", scope));
|
||||
rustc_pv.arg("--remap-path-prefix");
|
||||
rustc_pv.arg(format!("{}=/REMAPPED", cwd().display()));
|
||||
rustc_pv.arg("-Csplit-debuginfo=off");
|
||||
rustc_pv.run();
|
||||
|
||||
match dwarf_test {
|
||||
DwarfDump::AvoidSrcPath => {
|
||||
llvm_dwarfdump()
|
||||
.input(print_value_rlib)
|
||||
.run()
|
||||
.assert_stdout_not_contains("REMAPPED/src/some_value.rs")
|
||||
.assert_stdout_not_contains("REMAPPED/src/print_value.rs")
|
||||
.assert_stdout_not_contains("REMAPPED/REMAPPED")
|
||||
.assert_stdout_contains(cwd().join("src/some_value.rs").display().to_string())
|
||||
.assert_stdout_contains(cwd().join("src/print_value.rs").display().to_string());
|
||||
}
|
||||
DwarfDump::ContainsSrcPath => {
|
||||
llvm_dwarfdump()
|
||||
.input(print_value_rlib)
|
||||
.run()
|
||||
.assert_stdout_contains("REMAPPED/src/some_value.rs")
|
||||
.assert_stdout_contains("REMAPPED/src/print_value.rs")
|
||||
.assert_stdout_not_contains(cwd().join("src/some_value.rs").display().to_string())
|
||||
.assert_stdout_not_contains(cwd().join("src/print_value.rs").display().to_string());
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
extern crate some_value;
|
||||
|
||||
pub fn print_value() {
|
||||
println!("{}", some_value::get_some_value());
|
||||
}
|
||||
6
tests/run-make/remap-path-prefix-dwarf/src/some_value.rs
Normal file
6
tests/run-make/remap-path-prefix-dwarf/src/some_value.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
#[inline]
|
||||
pub fn get_some_value() -> i32 {
|
||||
42
|
||||
}
|
||||
@@ -47,10 +47,10 @@ fn main() {
|
||||
|
||||
out_object.run();
|
||||
rmeta_contains("/the/aux/lib.rs");
|
||||
rmeta_not_contains("auxiliary");
|
||||
rmeta_contains("auxiliary");
|
||||
out_macro.run();
|
||||
rmeta_contains("/the/aux/lib.rs");
|
||||
rmeta_not_contains("auxiliary");
|
||||
rmeta_contains("auxiliary");
|
||||
out_diagobj.run();
|
||||
rmeta_contains("/the/aux/lib.rs");
|
||||
rmeta_not_contains("auxiliary");
|
||||
@@ -58,6 +58,7 @@ fn main() {
|
||||
|
||||
//FIXME(Oneirical): These could be generalized into run_make_support
|
||||
// helper functions.
|
||||
#[track_caller]
|
||||
fn rmeta_contains(expected: &str) {
|
||||
// Normalize to account for path differences in Windows.
|
||||
if !bstr::BString::from(rfs::read("liblib.rmeta")).replace(b"\\", b"/").contains_str(expected) {
|
||||
@@ -69,6 +70,7 @@ fn rmeta_contains(expected: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn rmeta_not_contains(expected: &str) {
|
||||
// Normalize to account for path differences in Windows.
|
||||
if bstr::BString::from(rfs::read("liblib.rmeta")).replace(b"\\", b"/").contains_str(expected) {
|
||||
|
||||
Reference in New Issue
Block a user