Skip to content

Commit 548fca6

Browse files
authored
Rollup merge of #96562 - michaelwoerister:path-remapping-fixes, r=oli-obk
Fix duplicate directory separator in --remap-path-prefix. The compiler will currently emit duplicate directory separators when `--remap-path-prefix` has an exact match of the working directory and it is invoked with a relative path to the main source file. For example ```bash rustc src/main.rs -Cdebuginfo=2 --remap-path-prefix="$(pwd)=abc" ``` will produce the path `abc//src/main.rs` in debuginfo. This is because `some_path.join("")` will append a directory separator to `some_path` and then LLVM does not check if the working directory already ends a directory separator before concatenating it with the relative path.
2 parents 2986bef + 3614bd3 commit 548fca6

File tree

3 files changed

+94
-2
lines changed

3 files changed

+94
-2
lines changed

compiler/rustc_span/src/source_map.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,19 @@ impl FilePathMapping {
11021102
// take precedence.
11031103
for &(ref from, ref to) in self.mapping.iter().rev() {
11041104
if let Ok(rest) = path.strip_prefix(from) {
1105-
return (to.join(rest), true);
1105+
let remapped = if rest.as_os_str().is_empty() {
1106+
// This is subtle, joining an empty path onto e.g. `foo/bar` will
1107+
// result in `foo/bar/`, that is, there'll be an additional directory
1108+
// separator at the end. This can lead to duplicated directory separators
1109+
// in remapped paths down the line.
1110+
// So, if we have an exact match, we just return that without a call
1111+
// to `Path::join()`.
1112+
to.clone()
1113+
} else {
1114+
to.join(rest)
1115+
};
1116+
1117+
return (remapped, true);
11061118
}
11071119
}
11081120

compiler/rustc_span/src/source_map/tests.rs

+80
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,83 @@ impl SourceMapExtension for SourceMap {
312312
}
313313
}
314314
}
315+
316+
fn map_path_prefix(mapping: &FilePathMapping, path: &str) -> String {
317+
// It's important that we convert to a string here because that's what
318+
// later stages do too (e.g. in the backend), and comparing `Path` values
319+
// won't catch some differences at the string level, e.g. "abc" and "abc/"
320+
// compare as equal.
321+
mapping.map_prefix(path.into()).0.to_string_lossy().to_string()
322+
}
323+
324+
#[cfg(unix)]
325+
#[test]
326+
fn path_prefix_remapping() {
327+
// Relative to relative
328+
{
329+
let mapping = &FilePathMapping::new(vec![("abc/def".into(), "foo".into())]);
330+
331+
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), "foo/src/main.rs");
332+
assert_eq!(map_path_prefix(mapping, "abc/def"), "foo");
333+
}
334+
335+
// Relative to absolute
336+
{
337+
let mapping = &FilePathMapping::new(vec![("abc/def".into(), "/foo".into())]);
338+
339+
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), "/foo/src/main.rs");
340+
assert_eq!(map_path_prefix(mapping, "abc/def"), "/foo");
341+
}
342+
343+
// Absolute to relative
344+
{
345+
let mapping = &FilePathMapping::new(vec![("/abc/def".into(), "foo".into())]);
346+
347+
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), "foo/src/main.rs");
348+
assert_eq!(map_path_prefix(mapping, "/abc/def"), "foo");
349+
}
350+
351+
// Absolute to absolute
352+
{
353+
let mapping = &FilePathMapping::new(vec![("/abc/def".into(), "/foo".into())]);
354+
355+
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), "/foo/src/main.rs");
356+
assert_eq!(map_path_prefix(mapping, "/abc/def"), "/foo");
357+
}
358+
}
359+
360+
#[cfg(windows)]
361+
#[test]
362+
fn path_prefix_remapping_from_relative2() {
363+
// Relative to relative
364+
{
365+
let mapping = &FilePathMapping::new(vec![("abc\\def".into(), "foo".into())]);
366+
367+
assert_eq!(map_path_prefix(mapping, "abc\\def\\src\\main.rs"), "foo\\src\\main.rs");
368+
assert_eq!(map_path_prefix(mapping, "abc\\def"), "foo");
369+
}
370+
371+
// Relative to absolute
372+
{
373+
let mapping = &FilePathMapping::new(vec![("abc\\def".into(), "X:\\foo".into())]);
374+
375+
assert_eq!(map_path_prefix(mapping, "abc\\def\\src\\main.rs"), "X:\\foo\\src\\main.rs");
376+
assert_eq!(map_path_prefix(mapping, "abc\\def"), "X:\\foo");
377+
}
378+
379+
// Absolute to relative
380+
{
381+
let mapping = &FilePathMapping::new(vec![("X:\\abc\\def".into(), "foo".into())]);
382+
383+
assert_eq!(map_path_prefix(mapping, "X:\\abc\\def\\src\\main.rs"), "foo\\src\\main.rs");
384+
assert_eq!(map_path_prefix(mapping, "X:\\abc\\def"), "foo");
385+
}
386+
387+
// Absolute to absolute
388+
{
389+
let mapping = &FilePathMapping::new(vec![("X:\\abc\\def".into(), "X:\\foo".into())]);
390+
391+
assert_eq!(map_path_prefix(mapping, "X:\\abc\\def\\src\\main.rs"), "X:\\foo\\src\\main.rs");
392+
assert_eq!(map_path_prefix(mapping, "X:\\abc\\def"), "X:\\foo");
393+
}
394+
}

src/test/codegen/remap_path_prefix/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn main() {
2222
}
2323

2424
// Here we check that local debuginfo is mapped correctly.
25-
// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd/"
25+
// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd"
2626

2727
// And here that debuginfo from other crates are expanded to absolute paths.
2828
// CHECK: !DIFile(filename: "/the/aux-src/remap_path_prefix_aux.rs", directory: ""

0 commit comments

Comments
 (0)