Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use rustc_session::utils::{CanonicalizedPath, NativeLib};
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, getopts};
use rustc_span::edition::{DEFAULT_EDITION, Edition};
use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
use rustc_span::{FileName, SourceFileHashAlgorithm, sym};
use rustc_span::{FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, sym};
use rustc_target::spec::{
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel,
Expand Down Expand Up @@ -175,6 +175,33 @@ fn test_can_print_warnings() {
});
}

// `-Zremap-cwd-prefix` must not be merged into the tracked `remap_path_prefix` option:
// storing the absolute cwd there invalidates the incremental cache across build
// directories (see #132132). It must instead be applied via `file_path_mapping`.
#[test]
fn test_remap_cwd_prefix_not_in_remap_path_prefix() {
sess_and_cfg(
&["--remap-path-prefix=/explicit=mapped", "-Zremap-cwd-prefix=cwd-mapped"],
|sess, _cfg| {
// The tracked option holds only the explicit `--remap-path-prefix` entry.
assert_eq!(
sess.opts.remap_path_prefix,
vec![(PathBuf::from("/explicit"), PathBuf::from("mapped"))],
);

// ... but the cwd remapping is still applied via `file_path_mapping`.
let cwd = std::env::current_dir().unwrap();
let remapped = sess
.opts
.file_path_mapping()
.to_real_filename(&RealFileName::empty(), cwd.join("foo.rs"))
.path(RemapPathScopeComponents::DEBUGINFO)
.to_path_buf();
assert_eq!(remapped, PathBuf::from("cwd-mapped/foo.rs"));
},
);
}

#[test]
fn test_output_types_tracking_hash_different_paths() {
let mut v1 = Options::default();
Expand Down
44 changes: 28 additions & 16 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1375,9 +1375,21 @@ pub fn host_tuple() -> &'static str {

fn file_path_mapping(
remap_path_prefix: Vec<(PathBuf, PathBuf)>,
remap_cwd_prefix: Option<&Path>,
remap_path_scope: RemapPathScopeComponents,
) -> FilePathMapping {
FilePathMapping::new(remap_path_prefix.clone(), remap_path_scope)
// Apply `-Zremap-cwd-prefix` here rather than in `parse_remap_path_prefix`, so the
// absolute cwd is never stored in the tracked `remap_path_prefix` option (#132132).
let cwd_remap = if let Some(to) = remap_cwd_prefix
&& let Ok(cwd) = std::env::current_dir()
{
Some((cwd, to.to_path_buf()))
} else {
None
};
// The cwd remapping is appended last: `map_prefix` tries entries in reverse order, so this
// keeps `-Zremap-cwd-prefix` taking precedence over `--remap-path-prefix`, as documented.
FilePathMapping::new(remap_path_prefix.into_iter().chain(cwd_remap).collect(), remap_path_scope)
}

impl Default for Options {
Expand All @@ -1389,7 +1401,8 @@ impl Default for Options {
// to create a default working directory.
let working_dir = {
let working_dir = std::env::current_dir().unwrap();
let file_mapping = file_path_mapping(Vec::new(), RemapPathScopeComponents::empty());
let file_mapping =
file_path_mapping(Vec::new(), None, RemapPathScopeComponents::empty());
file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
};

Expand Down Expand Up @@ -1450,7 +1463,11 @@ impl Options {
}

pub fn file_path_mapping(&self) -> FilePathMapping {
file_path_mapping(self.remap_path_prefix.clone(), self.remap_path_scope)
file_path_mapping(
self.remap_path_prefix.clone(),
self.unstable_opts.remap_cwd_prefix.as_deref(),
self.remap_path_scope,
)
}

/// Returns `true` if there will be an output file generated.
Expand Down Expand Up @@ -2384,9 +2401,8 @@ pub fn parse_externs(
fn parse_remap_path_prefix(
early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
) -> Vec<(PathBuf, PathBuf)> {
let mut mapping: Vec<(PathBuf, PathBuf)> = matches
matches
.opt_strs("remap-path-prefix")
.into_iter()
.map(|remap| match remap.rsplit_once('=') {
Expand All @@ -2395,15 +2411,7 @@ fn parse_remap_path_prefix(
}
Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
})
.collect();
match &unstable_opts.remap_cwd_prefix {
Some(to) => match std::env::current_dir() {
Ok(cwd) => mapping.push((cwd, to.clone())),
Err(_) => (),
},
None => (),
};
mapping
.collect()
}

fn parse_logical_env(
Expand Down Expand Up @@ -2661,7 +2669,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M

let externs = parse_externs(early_dcx, matches, &unstable_opts);

let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches);
let remap_path_scope = parse_remap_path_scope(early_dcx, matches, &unstable_opts);

let pretty = parse_pretty(early_dcx, &unstable_opts);
Expand Down Expand Up @@ -2729,7 +2737,11 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
});

let file_mapping = file_path_mapping(remap_path_prefix.clone(), remap_path_scope);
let file_mapping = file_path_mapping(
remap_path_prefix.clone(),
unstable_opts.remap_cwd_prefix.as_deref(),
remap_path_scope,
);
file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
};

Expand Down
6 changes: 6 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ directory from build output, while allowing the command line to be universally
reproducible, such that the same execution will work on all machines, regardless
of build environment.

Unlike passing the equivalent mapping through `--remap-path-prefix`, the current
working directory does not take part in incremental compilation's dependency
tracking. Building the same sources from different directories (for example, a
sandboxed or per-build checkout path) therefore reuses the incremental cache
rather than invalidating it.

## Example
```sh
# This would produce an absolute path to main.rs in build outputs of
Expand Down
Loading