about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2022-04-29 19:36:02 +0200
committerMichael Woerister <michaelwoerister@posteo>2022-04-29 21:09:12 +0200
commit3614bd3c45a8d0e5f27c0736e8966f6456a5cd75 (patch)
treedcc587efaf03c52083600d83693bc08364a1d57c
parent683c582c1e88c573c454b7fa6f00bc6647421864 (diff)
downloadrust-3614bd3c45a8d0e5f27c0736e8966f6456a5cd75.tar.gz
rust-3614bd3c45a8d0e5f27c0736e8966f6456a5cd75.zip
Fix duplicate directory separator in --remap-path-prefix.
-rw-r--r--compiler/rustc_span/src/source_map.rs14
-rw-r--r--compiler/rustc_span/src/source_map/tests.rs80
-rw-r--r--src/test/codegen/remap_path_prefix/main.rs2
3 files changed, 94 insertions, 2 deletions
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 95177102dcf..460b5c18fc1 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -1102,7 +1102,19 @@ impl FilePathMapping {
         //       take precedence.
         for &(ref from, ref to) in self.mapping.iter().rev() {
             if let Ok(rest) = path.strip_prefix(from) {
-                return (to.join(rest), true);
+                let remapped = if rest.as_os_str().is_empty() {
+                    // This is subtle, joining an empty path onto e.g. `foo/bar` will
+                    // result in `foo/bar/`, that is, there'll be an additional directory
+                    // separator at the end. This can lead to duplicated directory separators
+                    // in remapped paths down the line.
+                    // So, if we have an exact match, we just return that without a call
+                    // to `Path::join()`.
+                    to.clone()
+                } else {
+                    to.join(rest)
+                };
+
+                return (remapped, true);
             }
         }
 
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index f13979941ab..481e015c66c 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -312,3 +312,83 @@ impl SourceMapExtension for SourceMap {
         }
     }
 }
+
+fn map_path_prefix(mapping: &FilePathMapping, path: &str) -> String {
+    // It's important that we convert to a string here because that's what
+    // later stages do too (e.g. in the backend), and comparing `Path` values
+    // won't catch some differences at the string level, e.g. "abc" and "abc/"
+    // compare as equal.
+    mapping.map_prefix(path.into()).0.to_string_lossy().to_string()
+}
+
+#[cfg(unix)]
+#[test]
+fn path_prefix_remapping() {
+    // Relative to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("abc/def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), "foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc/def"), "foo");
+    }
+
+    // Relative to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("abc/def".into(), "/foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), "/foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc/def"), "/foo");
+    }
+
+    // Absolute to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("/abc/def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), "foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "/abc/def"), "foo");
+    }
+
+    // Absolute to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("/abc/def".into(), "/foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), "/foo/src/main.rs");
+        assert_eq!(map_path_prefix(mapping, "/abc/def"), "/foo");
+    }
+}
+
+#[cfg(windows)]
+#[test]
+fn path_prefix_remapping_from_relative2() {
+    // Relative to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("abc\\def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc\\def\\src\\main.rs"), "foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc\\def"), "foo");
+    }
+
+    // Relative to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("abc\\def".into(), "X:\\foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "abc\\def\\src\\main.rs"), "X:\\foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "abc\\def"), "X:\\foo");
+    }
+
+    // Absolute to relative
+    {
+        let mapping = &FilePathMapping::new(vec![("X:\\abc\\def".into(), "foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def\\src\\main.rs"), "foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def"), "foo");
+    }
+
+    // Absolute to absolute
+    {
+        let mapping = &FilePathMapping::new(vec![("X:\\abc\\def".into(), "X:\\foo".into())]);
+
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def\\src\\main.rs"), "X:\\foo\\src\\main.rs");
+        assert_eq!(map_path_prefix(mapping, "X:\\abc\\def"), "X:\\foo");
+    }
+}
diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs
index 698dfe6b4f3..b13d576295c 100644
--- a/src/test/codegen/remap_path_prefix/main.rs
+++ b/src/test/codegen/remap_path_prefix/main.rs
@@ -22,7 +22,7 @@ fn main() {
 }
 
 // Here we check that local debuginfo is mapped correctly.
-// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd/"
+// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd"
 
 // And here that debuginfo from other crates are expanded to absolute paths.
 // CHECK: !DIFile(filename: "/the/aux-src/remap_path_prefix_aux.rs", directory: ""