Change:
I just got this backtrace when running on salsa-rs/salsa The remapping from paths to the rust-src component only seems to kick in once here, but I expected it to always work (since the component is installed). Frames 6 and 7 also point to the exact same location, but path remapping still failed for one of them.
what version of rustc is this?
This is on
Can you try with latest nightly? was merged recently and may have fixed this.
The most recent nightly seems to work even less:
what do you mean? Those look correctly remapped to /rustc/hash to me, were you expecting something else?
Oh I see, you want it to not remap and use the local path.
Note that people have requested the opposite behavior in the past, but it seems reasonable to do this only for tests:
(my mistake, the terminology used here wasn't clear to me)
cc
I see there are some terminology confusions. are technically remapped as it was remapped from some real path during compiler bootstrapping. At compile time it's correlated back to path if it exists. I would call "virtualised" path and the actual path "real" or "local" path. I'm not confident in saying this but I think this can be resolved within ? This avoids emitting local paths into the binary which was what we tried to avoid.
I haven't looked into the code, but that sounds like it's a compile time constant, so it has the path when rustc is compiled, not when rustc is running. So if you use that it will be unhelpful, it will show things like /home/bors/builds.
nvm actually contains what the path is virtualised to (i.e. ), so it's not too useful here. (It may be used to identify if the path on hand is actually for the Rust source rather than a real path on local system coincidentally starting with but that'd be highly unlikely unless the user is deliberately trying to trip things up. In any case we could hardcode into rustc during bootstrapping). The bit that finds the local path to rust source is here The only environment-dependent thing we need here is sysroot on the local file system. Obviously we can't emit that into the binary so maybe we could ask Cargo to supply it?
that has the same issue, cargo runs at compiletime, not runtime. There's no way for this to be done at runtime without it being part of the binary, which is why I suggested doing it only for test binaries.
I guess as an alternative libtest could read a SYSROOT environment variable set by cargo, but that seems kind of hacky.
I'm in the middle of writing an RFC for Cargo that adds a profile setting called , which is basically an implementation of (sanitising every potential absolute paths, like paths to Cargo registry) and is enabled by default for release builds. Prehaps we could make the emission of virtual vs real sysroot paths also dependant on that? It seems a logical thing to do if gets . This way both test and debug builds will have real paths embedded by default, and can be overriden manually if the user wishes.
RFC's here:

Discussion:
); for virtual_dir in virtual_rust_source_base_dir.iter().flatten() { <del> if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { if let rustc_span::FileName::Real(old_name) = name { if let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } = old_name { if let Ok(rest) = virtual_name.strip_prefix(virtual_dir) { let virtual_name = virtual_name.clone(); // The std library crates are in // `$sysroot/lib/rustlib/src/rust/library`, whereas other crates // may be in `$sysroot/lib/rustlib/src/rust/` directly. So we // detect crates from the std libs and handle them specially. const STD_LIBS: &[&str] = &[ "core", "alloc", "std", "test", "term", "unwind", "proc_macro", "panic_abort", "panic_unwind", "profiler_builtins", "rtstartup", "rustc-std-workspace-core", "rustc-std-workspace-alloc", "rustc-std-workspace-std", "backtrace", ]; let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l)); let new_path = if is_std_lib { real_dir.join("library").join(rest) } else { real_dir.join(rest) }; debug!( "try_to_translate_virtual_to_real: `{}` -> `{}`", virtual_name.display(), new_path.display(), ); let new_name = rustc_span::RealFileName::Remapped { local_path: Some(new_path), virtual_name, }; *old_name = new_name; } </del> <ins> if let Some(real_dir) = &sess.opts.real_rust_source_base_dir && let rustc_span::FileName::Real(old_name) = name && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } = old_name && let Ok(rest) = virtual_name.strip_prefix(virtual_dir) { // The std library crates are in // `$sysroot/lib/rustlib/src/rust/library`, whereas other crates // may be in `$sysroot/lib/rustlib/src/rust/` directly. So we // detect crates from the std libs and handle them specially. const STD_LIBS: &[&str] = &[ "core", "alloc", "std", "test", "term", "unwind", "proc_macro", "panic_abort", "panic_unwind", "profiler_builtins", "rtstartup", "rustc-std-workspace-core", "rustc-std-workspace-alloc", "rustc-std-workspace-std", "backtrace", ]; let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l)); let new_path = if is_std_lib { real_dir.join("library").join(rest) } else { real_dir.join(rest) }; debug!( "try_to_translate_virtual_to_real: `{}` -> `{}`", virtual_name.display(), new_path.display(), ); // Check if the translated real path is affected by any user-requested // remaps via --remap-path-prefix. Apply them if so. // Note that this is a special case for imported rust-src paths specified by // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths. // Other imported paths are not currently remapped (see #66251). let (user_remapped, applied) = sess.source_map().path_mapping().map_prefix(&new_path); let new_name = if applied { rustc_span::RealFileName::Remapped { local_path: Some(new_path.clone()), virtual_name: user_remapped.to_path_buf(), </ins> } <del> } </del> <ins> } else { rustc_span::RealFileName::LocalPath(new_path) }; *old_name = new_name; </ins> } } };

const CWD: &str = "{{cwd}}"; const SRC_BASE: &str = "{{src-base}}"; const BUILD_BASE: &str = "{{build-base}}"; <ins> const RUST_SRC_BASE: &str = "{{rust-src-base}}"; </ins> const SYSROOT_BASE: &str = "{{sysroot-base}}"; const TARGET_LINKER: &str = "{{target-linker}}"; const TARGET: &str = "{{target}}";

value = value.replace(TARGET, &config.target); } <ins> if value.contains(RUST_SRC_BASE) { let src_base = config.sysroot_base.join("lib/rustlib/src/rust"); src_base.try_exists().expect(&*format!("{} should exists", src_base.display())); let src_base = src_base.read_link().unwrap_or(src_base); value = value.replace(RUST_SRC_BASE, &src_base.to_string_lossy()); } </ins> value }

} let base_dir = Path::new("/rustc/FAKE_PREFIX"); <del> // Paths into the libstd/libcore </del> <ins> // Fake paths into the libstd/libcore </ins> normalize_path(&base_dir.join("library"), "$SRC_DIR"); // `ui-fulldeps` tests can show paths to the compiler source when testing macros from // `rustc_macros` // eg. /home/user/rust/compiler normalize_path(&base_dir.join("compiler"), "$COMPILER_DIR"); <ins> // Real paths into the libstd/libcore let rust_src_dir = &self.config.sysroot_base.join("lib/rustlib/src/rust"); rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir.display())); let rust_src_dir = rust_src_dir.read_link().unwrap_or(rust_src_dir.to_path_buf()); normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL"); </ins> // Paths into the build directory let test_build_dir = &self.config.build_base; let parent_build_dir = test_build_dir.parent().unwrap().parent().unwrap().parent().unwrap();

// eg. /home/user/rust/build normalize_path(parent_build_dir, "$BUILD_DIR"); <del> // Paths into lib directory. normalize_path(&parent_build_dir.parent().unwrap().join("lib"), "$LIB_DIR"); </del> if json { // escaped newlines in json strings should be readable // in the stderr files. There's no point int being correct,

<ins> //@ revisions: with-remap without-remap //@ compile-flags: -g -Ztranslate-remapped-path-to-local-path=yes //@ [with-remap]compile-flags: --remap-path-prefix={{rust-src-base}}=remapped //@ [with-remap]compile-flags: --remap-path-prefix={{src-base}}=remapped-tests-ui //@ [without-remap]compile-flags: //@ error-pattern: E0507 // The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically // as the remapped revision will not begin with $SRC_DIR_REAL, // so we have to do it ourselves. //@ normalize-stderr-test: ".rs:d+:d+" -> ".rs:LL:COL" use std::thread; struct Worker { thread: thread::JoinHandle<()>, } impl Drop for Worker { fn drop(&mut self) { self.thread.join().unwrap(); } } pub fn main(){} </ins>

<ins> error[E0507]: cannot move out of `self.thread` which is behind a mutable reference --> remapped-tests-ui/errors/remap-path-prefix-sysroot.rs:LL:COL | LL |         self.thread.join().unwrap(); |         ^^^^^^^^^^^ ------ `self.thread` moved due to this method call |         | |         move occurs because `self.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait | note: `JoinHandle::<T>::join` takes ownership of the receiver `self`, which moves `self.thread` --> remapped/library/std/src/thread/mod.rs:LL:COL | LL |     pub fn join(self) -> Result<T> { |                 ^^^^ error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. </ins>

<ins> error[E0507]: cannot move out of `self.thread` which is behind a mutable reference --> $DIR/remap-path-prefix-sysroot.rs:LL:COL | LL |         self.thread.join().unwrap(); |         ^^^^^^^^^^^ ------ `self.thread` moved due to this method call |         | |         move occurs because `self.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait | note: `JoinHandle::<T>::join` takes ownership of the receiver `self`, which moves `self.thread` --> $SRC_DIR_REAL/std/src/thread/mod.rs:LL:COL | LL |     pub fn join(self) -> Result<T> { |                 ^^^^ error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. </ins>