Skip to content

Commit

Permalink
bootstrap: Add and use -Z absolute-file-paths
Browse files Browse the repository at this point in the history
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
```
  • Loading branch information
jyn514 committed Jun 19, 2023
1 parent 78bf242 commit f698f3c
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 2 deletions.
22 changes: 20 additions & 2 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(absolute_path)]
#![feature(lazy_cell)]
#![feature(decl_macro)]
#![recursion_limit = "256"]
Expand Down Expand Up @@ -303,7 +304,11 @@ fn run_compiler(
registry: diagnostics_registry(),
};

match make_input(config.opts.error_format, &matches.free) {
match make_input(
config.opts.error_format,
&matches.free,
config.opts.unstable_opts.absolute_file_paths,
) {
Err(reported) => return Err(reported),
Ok(Some(input)) => {
config.input = input;
Expand Down Expand Up @@ -476,6 +481,7 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileNa
fn make_input(
error_format: ErrorOutputType,
free_matches: &[String],
absolute_file_paths: bool,
) -> Result<Option<Input>, ErrorGuaranteed> {
if free_matches.len() == 1 {
let ifile = &free_matches[0];
Expand Down Expand Up @@ -503,7 +509,19 @@ fn make_input(
Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
}
} else {
Ok(Some(Input::File(PathBuf::from(ifile))))
let mut path = PathBuf::from(ifile);
if absolute_file_paths {
match std::path::absolute(path) {
Ok(p) => path = p,
Err(e) => {
return Err(early_error_no_abort(
error_format,
format!("failed to convert {ifile} to an absolute path: {e}"),
));
}
}
}
Ok(Some(Input::File(path)))
}
} else {
Ok(None)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,7 @@ fn test_unstable_options_tracking_hash() {

// Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
// tidy-alphabetical-start
untracked!(absolute_file_paths, true);
untracked!(assert_incr_state, Some(String::from("loaded")));
untracked!(deduplicate_diagnostics, false);
untracked!(dep_tasks, true);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,8 @@ options! {
// - src/doc/unstable-book/src/compiler-flags

// tidy-alphabetical-start
absolute_file_paths: bool = (false, parse_bool, [UNTRACKED],
"use absolute file paths in diagnostics, not relative paths (default: no)"),
allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
"only allow the listed language features to be enabled in code (comma separated)"),
always_encode_mir: bool = (false, parse_bool, [TRACKED],
Expand Down
16 changes: 16 additions & 0 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ def __init__(self):
self.verbose = False
self.git_version = None
self.nix_deps_dir = None
self.local_rebuild = False
self._should_fix_bins_and_dylibs = None

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

build.local_rebuild = build.get_toml("local_rebuild", "build")
if build.local_rebuild is None and not build.rustc().startswith(build.bin_root()):
with open(os.path.join(build.rust_root, "src", "version")) as f:
expected_version = f.read().split(".")[:2]
output = require([build.rustc(), "--version"]).decode(sys.getdefaultencoding())
actual_version = output.split(" ")[1].split(".")[:2]
if expected_version == actual_version:
if build.verbose:
print("auto-detected local-rebuild {}".format(actual_version))
build.local_rebuild = True

# Fetch/build the bootstrap
build.download_toolchain()
sys.stdout.flush()
Expand Down
5 changes: 5 additions & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,11 @@ impl<'a> Builder<'a> {
// cargo would implicitly add it, it was discover that sometimes bootstrap only use
// `rustflags` without `cargo` making it required.
rustflags.arg("-Zunstable-options");
// Make ctrl+click, etc. work with workspaces other than the root workspace.
// cfg(bootstrap)
if stage > 0 {
rustflags.arg("-Zabsolute-file-paths");
}
for (restricted_mode, name, values) in EXTRA_CHECK_CFGS {
if *restricted_mode == None || *restricted_mode == Some(mode) {
// Creating a string of the values by concatenating each value:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# `absolute-file-paths`

This features is currently perma-unstable, with no tracking issue.

------------------------

This feature allows you to configure rustc to print diagnostics and other output using absolute file paths, not relative file paths.

Set `-Zabsolute-file-paths` to enable this feature.

0 comments on commit f698f3c

Please sign in to comment.