about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2025-04-19 11:52:18 +0200
committerUrgau <urgau@numericable.fr>2025-05-05 19:45:34 +0200
commit6a7996e30325e28215b318feb7cc56bcff0e2bb5 (patch)
tree3234632c51dd0a72b05180fb53814f08d14d2cf8
parent6e23095adf9209614a45f7f75fea36dad7b92afb (diff)
downloadrust-6a7996e30325e28215b318feb7cc56bcff0e2bb5.tar.gz
rust-6a7996e30325e28215b318feb7cc56bcff0e2bb5.zip
Take into-account `-Zremap-path-scope` when embedding filenames
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_session/src/config.rs8
-rw-r--r--compiler/rustc_span/src/lib.rs34
-rw-r--r--compiler/rustc_span/src/source_map.rs80
-rw-r--r--compiler/rustc_span/src/source_map/tests.rs73
-rw-r--r--tests/run-make/remap-path-prefix-dwarf/rmake.rs53
-rw-r--r--tests/run-make/remap-path-prefix-dwarf/src/print_value.rs7
-rw-r--r--tests/run-make/remap-path-prefix-dwarf/src/some_value.rs6
-rw-r--r--tests/run-make/remap-path-prefix/rmake.rs6
9 files changed, 205 insertions, 64 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 3ea61d1b40a..e4cf58fccda 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -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);
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e2d36f6a4e2..ccb1e950960 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -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,
@@ -1316,6 +1317,11 @@ fn file_path_mapping(
         } else {
             FileNameDisplayPreference::Local
         },
+        if unstable_opts.remap_path_scope.is_all() {
+            FileNameEmbeddablePreference::RemappedOnly
+        } else {
+            FileNameEmbeddablePreference::LocalAndRemapped
+        },
     )
 }
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 9722031f209..6fcf77e31a2 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -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.
@@ -369,6 +347,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`.
     /// This is appropriate for paths that get embedded into files produced by the compiler.
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 0273bb040f4..8a3644163ca 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -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
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index 957f55e3913..589c2a36354 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -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 {
@@ -449,12 +454,78 @@ 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.
     {
         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!(
diff --git a/tests/run-make/remap-path-prefix-dwarf/rmake.rs b/tests/run-make/remap-path-prefix-dwarf/rmake.rs
index ede1d615742..3d6ca014fc2 100644
--- a/tests/run-make/remap-path-prefix-dwarf/rmake.rs
+++ b/tests/run-make/remap-path-prefix-dwarf/rmake.rs
@@ -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]
diff --git a/tests/run-make/remap-path-prefix-dwarf/src/print_value.rs b/tests/run-make/remap-path-prefix-dwarf/src/print_value.rs
new file mode 100644
index 00000000000..f7653025ba5
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-dwarf/src/print_value.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+
+extern crate some_value;
+
+pub fn print_value() {
+    println!("{}", some_value::get_some_value());
+}
diff --git a/tests/run-make/remap-path-prefix-dwarf/src/some_value.rs b/tests/run-make/remap-path-prefix-dwarf/src/some_value.rs
new file mode 100644
index 00000000000..aa95a1bdf73
--- /dev/null
+++ b/tests/run-make/remap-path-prefix-dwarf/src/some_value.rs
@@ -0,0 +1,6 @@
+#![crate_type = "rlib"]
+
+#[inline]
+pub fn get_some_value() -> i32 {
+    42
+}
diff --git a/tests/run-make/remap-path-prefix/rmake.rs b/tests/run-make/remap-path-prefix/rmake.rs
index aeb30e72d5b..b4f7f4769b5 100644
--- a/tests/run-make/remap-path-prefix/rmake.rs
+++ b/tests/run-make/remap-path-prefix/rmake.rs
@@ -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) {