Skip to content

Commit

Permalink
Auto merge of rust-lang#118149 - cbeuw:rfc3127-sysroot, r=b-naber
Browse files Browse the repository at this point in the history
Implement RFC 3127 sysroot path handling changes

Fix rust-lang#105907
Fix rust-lang#85463

Implement parts of rust-lang#111540

Right now, backtraces into sysroot always shows /rustc/$hash in diagnostics, e.g.

```
thread 'main' panicked at 'hello world', map-panic.rs:2:50
stack backtrace:
   0: std::panicking::begin_panic
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:616:12
   1: map_panic::main::{{closure}}
             at ./map-panic.rs:2:50
   2: core::option::Option<T>::map
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/option.rs:929:29
   3: map_panic::main
             at ./map-panic.rs:2:30
   4: core::ops::function::FnOnce::call_once
             at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```

[RFC 3127 said](https://rust-lang.github.io/rfcs/3127-trim-paths.html#changing-handling-of-sysroot-path-in-rustc)

> We want to change this behaviour such that, when rust-src source files can be discovered, the virtual path is discarded and therefore the local path will be embedded, unless there is a --remap-path-prefix that causes this local path to be remapped in the usual way.

This PR implements this behaviour. When `rust-src` is present at compile time, rustc replaces /rustc/$hash with a real path into local rust-src with best effort. To sanitise this, users must explicitly supply `--remap-path-prefix=<path to rust-src>=foo`.
  • Loading branch information
bors committed Dec 16, 2023
2 parents e223c41 + 0cba7c8 commit a05bc27
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 52 deletions.
105 changes: 56 additions & 49 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1597,56 +1597,63 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
);

for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
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;
}
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(),
}
}
} else {
rustc_span::RealFileName::LocalPath(new_path)
};
*old_name = new_name;
}
}
};
Expand Down
10 changes: 10 additions & 0 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ fn expand_variables(mut value: String, config: &Config) -> String {
const CWD: &str = "{{cwd}}";
const SRC_BASE: &str = "{{src-base}}";
const BUILD_BASE: &str = "{{build-base}}";
const RUST_SRC_BASE: &str = "{{rust-src-base}}";

if value.contains(CWD) {
let cwd = env::current_dir().unwrap();
Expand All @@ -809,6 +810,15 @@ fn expand_variables(mut value: String, config: &Config) -> String {
value = value.replace(BUILD_BASE, &config.build_base.to_string_lossy());
}

if value.contains(RUST_SRC_BASE) {
let src_base = config
.sysroot_base
.join("lib/rustlib/src/rust")
.read_link()
.expect("lib/rustlib/src/rust in target is a symlink to checkout root");
value = value.replace(RUST_SRC_BASE, &src_base.to_string_lossy());
}

value
}

Expand Down
12 changes: 9 additions & 3 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4205,7 +4205,7 @@ impl<'test> TestCx<'test> {
}

let base_dir = Path::new("/rustc/FAKE_PREFIX");
// Paths into the libstd/libcore
// Fake paths into the libstd/libcore
normalize_path(&base_dir.join("library"), "$SRC_DIR");
// `ui-fulldeps` tests can show paths to the compiler source when testing macros from
// `rustc_macros`
Expand All @@ -4221,8 +4221,14 @@ impl<'test> TestCx<'test> {
// eg. /home/user/rust/build
normalize_path(parent_build_dir, "$BUILD_DIR");

// Paths into lib directory.
normalize_path(&parent_build_dir.parent().unwrap().join("lib"), "$LIB_DIR");
// Real paths into the libstd/libcore
let rust_src_dir = &self
.config
.sysroot_base
.join("lib/rustlib/src/rust")
.read_link()
.expect("lib/rustlib/src/rust in target is a symlink to checkout root");
normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL");

if json {
// escaped newlines in json strings should be readable
Expand Down
23 changes: 23 additions & 0 deletions tests/ui/errors/remap-path-prefix-sysroot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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
// [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(){}
17 changes: 17 additions & 0 deletions tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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`.
17 changes: 17 additions & 0 deletions tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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`.

0 comments on commit a05bc27

Please sign in to comment.