Skip to content

Commit f698f3c

Browse files
committed
bootstrap: Add and use -Z absolute-file-paths
It's unfortunate that this hack is necessary. A short summary of the background here: - Rust-Analyzer uses `x check --json-output` to show red underlines in the editor. - There are several different Cargo workspaces in rust-lang/rust, including src/bootstrap and src/tools/miri. - Cargo runs each invocation of rustc relative to the *workspace*, not to the current working directory of cargo itself. - Rustc prints file paths relative to its current working directory. As a result, it would print things like `config.rs:43:14` instead of `src/bootstrap/config.rs`. This adds a new flag to rustc to print the files as an absolute path instead of a relative path. I went with this approach instead of one of the wrapping tools for the following reasons: 1. Cargo considers changing the working directory to be a breaking change: rust-lang/cargo#11007 (comment). They have open feature requests for adding a flag to print absolute paths, but none have been implemented. 2. Bootstrap would potentially be able to parse and rewrite the paths that cargo emits, but I don't want to hard-code Cargo's JSON output format in both bootstrap.py and rustbuild; unlike rustbuild, bootstrap.py can't use `cargo_metadata` as a library. 3. Rust-Analyzer could potentially rewrite this output, but that wouldn't fix ctrl+click on the relative path when someone runs `cargo check`. In addition to adding and using the new flag, this also adds `local_rebuild` detection to bootstrap.py, so that I could test the change. Before: ``` error[E0425]: cannot find value `MIRI_DEFAULT_ARGS` in crate `miri` --> src/bin/miri.rs:269:33 | 269 | args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string)); | ^^^^^^^^^^^^^^^^^ help: a constant with a similar name exists: `MIRI_DEFLT_ARGS` | ::: src/lib.rs:128:1 | 128 | pub const MIRI_DEFLT_ARGS: &[&str] = &[ | ---------------------------------- similarly named constant `MIRI_DEFLT_ARGS` defined here ``` After: ``` error[E0425]: cannot find value `MIRI_DEFAULT_ARGS` in crate `miri` --> /home/jyn/src/rust/src/tools/miri/src/bin/miri.rs:269:33 | 269 | args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string)); | ^^^^^^^^^^^^^^^^^ help: a constant with a similar name exists: `MIRI_DEFLT_ARGS` | ::: /home/jyn/src/rust/src/tools/miri/src/lib.rs:128:1 | 128 | pub const MIRI_DEFLT_ARGS: &[&str] = &[ | ---------------------------------- similarly named constant `MIRI_DEFLT_ARGS` defined here ```
1 parent 78bf242 commit f698f3c

File tree

6 files changed

+53
-2
lines changed

6 files changed

+53
-2
lines changed

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! This API is completely unstable and subject to change.
66
77
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
8+
#![feature(absolute_path)]
89
#![feature(lazy_cell)]
910
#![feature(decl_macro)]
1011
#![recursion_limit = "256"]
@@ -303,7 +304,11 @@ fn run_compiler(
303304
registry: diagnostics_registry(),
304305
};
305306

306-
match make_input(config.opts.error_format, &matches.free) {
307+
match make_input(
308+
config.opts.error_format,
309+
&matches.free,
310+
config.opts.unstable_opts.absolute_file_paths,
311+
) {
307312
Err(reported) => return Err(reported),
308313
Ok(Some(input)) => {
309314
config.input = input;
@@ -476,6 +481,7 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileNa
476481
fn make_input(
477482
error_format: ErrorOutputType,
478483
free_matches: &[String],
484+
absolute_file_paths: bool,
479485
) -> Result<Option<Input>, ErrorGuaranteed> {
480486
if free_matches.len() == 1 {
481487
let ifile = &free_matches[0];
@@ -503,7 +509,19 @@ fn make_input(
503509
Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
504510
}
505511
} else {
506-
Ok(Some(Input::File(PathBuf::from(ifile))))
512+
let mut path = PathBuf::from(ifile);
513+
if absolute_file_paths {
514+
match std::path::absolute(path) {
515+
Ok(p) => path = p,
516+
Err(e) => {
517+
return Err(early_error_no_abort(
518+
error_format,
519+
format!("failed to convert {ifile} to an absolute path: {e}"),
520+
));
521+
}
522+
}
523+
}
524+
Ok(Some(Input::File(path)))
507525
}
508526
} else {
509527
Ok(None)

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ fn test_unstable_options_tracking_hash() {
657657

658658
// Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
659659
// tidy-alphabetical-start
660+
untracked!(absolute_file_paths, true);
660661
untracked!(assert_incr_state, Some(String::from("loaded")));
661662
untracked!(deduplicate_diagnostics, false);
662663
untracked!(dep_tasks, true);

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,8 @@ options! {
13521352
// - src/doc/unstable-book/src/compiler-flags
13531353

13541354
// tidy-alphabetical-start
1355+
absolute_file_paths: bool = (false, parse_bool, [UNTRACKED],
1356+
"use absolute file paths in diagnostics, not relative paths (default: no)"),
13551357
allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
13561358
"only allow the listed language features to be enabled in code (comma separated)"),
13571359
always_encode_mir: bool = (false, parse_bool, [TRACKED],

src/bootstrap/bootstrap.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ def __init__(self):
474474
self.verbose = False
475475
self.git_version = None
476476
self.nix_deps_dir = None
477+
self.local_rebuild = False
477478
self._should_fix_bins_and_dylibs = None
478479

479480
def download_toolchain(self):
@@ -894,6 +895,10 @@ def build_bootstrap(self, color, warnings, verbose_count):
894895
if target_linker is not None:
895896
env["RUSTFLAGS"] += " -C linker=" + target_linker
896897
env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes"
898+
# Make sure that rust-analyzer can map error diagnostics to the file.
899+
# cfg(bootstrap)
900+
if self.local_rebuild:
901+
env["RUSTFLAGS"] += " -Zabsolute-file-paths"
897902
if warnings == "default":
898903
deny_warnings = self.get_toml("deny-warnings", "rust") != "false"
899904
else:
@@ -1054,6 +1059,17 @@ def bootstrap(args):
10541059
if not os.path.exists(build.build_dir):
10551060
os.makedirs(build.build_dir)
10561061

1062+
build.local_rebuild = build.get_toml("local_rebuild", "build")
1063+
if build.local_rebuild is None and not build.rustc().startswith(build.bin_root()):
1064+
with open(os.path.join(build.rust_root, "src", "version")) as f:
1065+
expected_version = f.read().split(".")[:2]
1066+
output = require([build.rustc(), "--version"]).decode(sys.getdefaultencoding())
1067+
actual_version = output.split(" ")[1].split(".")[:2]
1068+
if expected_version == actual_version:
1069+
if build.verbose:
1070+
print("auto-detected local-rebuild {}".format(actual_version))
1071+
build.local_rebuild = True
1072+
10571073
# Fetch/build the bootstrap
10581074
build.download_toolchain()
10591075
sys.stdout.flush()

src/bootstrap/builder.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,11 @@ impl<'a> Builder<'a> {
13921392
// cargo would implicitly add it, it was discover that sometimes bootstrap only use
13931393
// `rustflags` without `cargo` making it required.
13941394
rustflags.arg("-Zunstable-options");
1395+
// Make ctrl+click, etc. work with workspaces other than the root workspace.
1396+
// cfg(bootstrap)
1397+
if stage > 0 {
1398+
rustflags.arg("-Zabsolute-file-paths");
1399+
}
13951400
for (restricted_mode, name, values) in EXTRA_CHECK_CFGS {
13961401
if *restricted_mode == None || *restricted_mode == Some(mode) {
13971402
// Creating a string of the values by concatenating each value:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# `absolute-file-paths`
2+
3+
This features is currently perma-unstable, with no tracking issue.
4+
5+
------------------------
6+
7+
This feature allows you to configure rustc to print diagnostics and other output using absolute file paths, not relative file paths.
8+
9+
Set `-Zabsolute-file-paths` to enable this feature.

0 commit comments

Comments
 (0)