Change:
); 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> } } };

Discussion:
Spawned off of I tried this code: I expected to see this happen: I expected the to be mapped to the local paths in the installed component, rather than being left as raw Instead, this happened: is showing up in the output. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --:
see related discussion from wg-debugging triage
in particular, pointed out that that this remapping should be happening if one has the component installed, and that the code doing the remapping should be executed here: and there is corresponding code in bootstrap dist code: There's some useful statements mixed in there, I bet we might be able to figure out what's going on here without too much trickery...
But this is currently a remapping at runtime only when using like in UI tests, right ? Otherwise it's optionally done at compile-time on the dist builders if they set .
is , right? That is what it is mapped from, not what it is mapped to.
Its and 's presence seem to control (at rustc build-time and at runtime respectively) whether the remapping happens in the code you listed above (otherwise would be "empty" and would be a no-op), so I may be missing how this could already remap to the local component according to Felix's comment above ?
I believe these are not being remapped on purpose (based on ). I think currently the remapping only happens for diagnostics (and not things that end up in the binary). There's some more discussion in (and and to some degree). There's also concerns about how it can affect binary size (). also discusses it some.
These paths are also not being remapped even when explicitly requested with

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: