mirror of https://github.com/rust-lang/rust.git
Auto merge of #84233 - jyn514:track-path-prefix, r=michaelwoerister
Add TRACKED_NO_CRATE_HASH and use it for `--remap-path-prefix` I verified locally that this fixes https://github.com/rust-lang/rust/issues/66955. r? `@Aaron1011` (feel free to reassign)
This commit is contained in:
commit
814a560072
|
@ -104,7 +104,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
|||
// Fortunately, we just checked that this isn't the case.
|
||||
let path = dep_graph_path_from(&sess.incr_comp_session_dir());
|
||||
let report_incremental_info = sess.opts.debugging_opts.incremental_info;
|
||||
let expected_hash = sess.opts.dep_tracking_hash();
|
||||
let expected_hash = sess.opts.dep_tracking_hash(false);
|
||||
|
||||
let mut prev_work_products = FxHashMap::default();
|
||||
let nightly_build = sess.is_nightly_build();
|
||||
|
|
|
@ -219,7 +219,7 @@ pub fn build_dep_graph(
|
|||
}
|
||||
|
||||
// First encode the commandline arguments hash
|
||||
if let Err(err) = sess.opts.dep_tracking_hash().encode(&mut encoder) {
|
||||
if let Err(err) = sess.opts.dep_tracking_hash(false).encode(&mut encoder) {
|
||||
sess.err(&format!(
|
||||
"failed to write dependency graph hash `{}`: {}",
|
||||
path_buf.display(),
|
||||
|
|
|
@ -19,6 +19,7 @@ use rustc_span::symbol::sym;
|
|||
use rustc_span::SourceFileHashAlgorithm;
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
|
||||
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel};
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::iter::FromIterator;
|
||||
use std::num::NonZeroUsize;
|
||||
|
@ -74,6 +75,27 @@ fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> {
|
|||
BTreeMap::from_iter(entries.into_iter())
|
||||
}
|
||||
|
||||
fn assert_same_clone(x: &Options) {
|
||||
assert_eq!(x.dep_tracking_hash(true), x.clone().dep_tracking_hash(true));
|
||||
assert_eq!(x.dep_tracking_hash(false), x.clone().dep_tracking_hash(false));
|
||||
}
|
||||
|
||||
fn assert_same_hash(x: &Options, y: &Options) {
|
||||
assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
|
||||
assert_eq!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
|
||||
// Check clone
|
||||
assert_same_clone(x);
|
||||
assert_same_clone(y);
|
||||
}
|
||||
|
||||
fn assert_different_hash(x: &Options, y: &Options) {
|
||||
assert_ne!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
|
||||
assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
|
||||
// Check clone
|
||||
assert_same_clone(x);
|
||||
assert_same_clone(y);
|
||||
}
|
||||
|
||||
// When the user supplies --test we should implicitly supply --cfg test
|
||||
#[test]
|
||||
fn test_switch_implies_cfg_test() {
|
||||
|
@ -130,14 +152,9 @@ fn test_output_types_tracking_hash_different_paths() {
|
|||
v2.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]);
|
||||
v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
|
||||
|
||||
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
|
||||
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
|
||||
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
|
||||
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
|
||||
assert_different_hash(&v1, &v2);
|
||||
assert_different_hash(&v1, &v3);
|
||||
assert_different_hash(&v2, &v3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -155,10 +172,7 @@ fn test_output_types_tracking_hash_different_construction_order() {
|
|||
(OutputType::Exe, Some(PathBuf::from("./some/thing"))),
|
||||
]);
|
||||
|
||||
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_same_hash(&v1, &v2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -182,14 +196,9 @@ fn test_externs_tracking_hash_different_construction_order() {
|
|||
(String::from("d"), new_public_extern_entry(vec!["f", "e"])),
|
||||
]));
|
||||
|
||||
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
|
||||
assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
|
||||
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
|
||||
assert_same_hash(&v1, &v2);
|
||||
assert_same_hash(&v1, &v3);
|
||||
assert_same_hash(&v2, &v3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -219,14 +228,9 @@ fn test_lints_tracking_hash_different_values() {
|
|||
(String::from("d"), Level::Deny),
|
||||
];
|
||||
|
||||
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
|
||||
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
|
||||
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
|
||||
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
|
||||
assert_different_hash(&v1, &v2);
|
||||
assert_different_hash(&v1, &v3);
|
||||
assert_different_hash(&v2, &v3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -248,11 +252,7 @@ fn test_lints_tracking_hash_different_construction_order() {
|
|||
(String::from("d"), Level::Forbid),
|
||||
];
|
||||
|
||||
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
|
||||
assert_same_hash(&v1, &v2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -292,15 +292,9 @@ fn test_search_paths_tracking_hash_different_order() {
|
|||
v4.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON));
|
||||
v4.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON));
|
||||
|
||||
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
|
||||
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
|
||||
assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
|
||||
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
|
||||
assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
|
||||
assert_same_hash(&v1, &v2);
|
||||
assert_same_hash(&v1, &v3);
|
||||
assert_same_hash(&v1, &v4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -338,15 +332,9 @@ fn test_native_libs_tracking_hash_different_values() {
|
|||
(String::from("c"), None, NativeLibKind::Unspecified),
|
||||
];
|
||||
|
||||
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
|
||||
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
|
||||
assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
|
||||
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
|
||||
assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
|
||||
assert_different_hash(&v1, &v2);
|
||||
assert_different_hash(&v1, &v3);
|
||||
assert_different_hash(&v1, &v4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -374,14 +362,9 @@ fn test_native_libs_tracking_hash_different_order() {
|
|||
(String::from("b"), None, NativeLibKind::Framework),
|
||||
];
|
||||
|
||||
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
|
||||
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
|
||||
assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash());
|
||||
|
||||
// Check clone
|
||||
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
|
||||
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
|
||||
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
|
||||
assert_same_hash(&v1, &v2);
|
||||
assert_same_hash(&v1, &v3);
|
||||
assert_same_hash(&v2, &v3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -391,8 +374,9 @@ fn test_codegen_options_tracking_hash() {
|
|||
|
||||
macro_rules! untracked {
|
||||
($name: ident, $non_default_value: expr) => {
|
||||
assert_ne!(opts.cg.$name, $non_default_value);
|
||||
opts.cg.$name = $non_default_value;
|
||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||
assert_same_hash(&reference, &opts);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -416,8 +400,9 @@ fn test_codegen_options_tracking_hash() {
|
|||
macro_rules! tracked {
|
||||
($name: ident, $non_default_value: expr) => {
|
||||
opts = reference.clone();
|
||||
assert_ne!(opts.cg.$name, $non_default_value);
|
||||
opts.cg.$name = $non_default_value;
|
||||
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||
assert_different_hash(&reference, &opts);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -454,6 +439,32 @@ fn test_codegen_options_tracking_hash() {
|
|||
tracked!(target_feature, String::from("all the features, all of them"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_top_level_options_tracked_no_crate() {
|
||||
let reference = Options::default();
|
||||
let mut opts;
|
||||
|
||||
macro_rules! tracked {
|
||||
($name: ident, $non_default_value: expr) => {
|
||||
opts = reference.clone();
|
||||
assert_ne!(opts.$name, $non_default_value);
|
||||
opts.$name = $non_default_value;
|
||||
// The crate hash should be the same
|
||||
assert_eq!(reference.dep_tracking_hash(true), opts.dep_tracking_hash(true));
|
||||
// The incremental hash should be different
|
||||
assert_ne!(reference.dep_tracking_hash(false), opts.dep_tracking_hash(false));
|
||||
};
|
||||
}
|
||||
|
||||
// Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash.
|
||||
// This list is in alphabetical order.
|
||||
tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
|
||||
tracked!(
|
||||
real_rust_source_base_dir,
|
||||
Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debugging_options_tracking_hash() {
|
||||
let reference = Options::default();
|
||||
|
@ -461,8 +472,9 @@ fn test_debugging_options_tracking_hash() {
|
|||
|
||||
macro_rules! untracked {
|
||||
($name: ident, $non_default_value: expr) => {
|
||||
assert_ne!(opts.debugging_opts.$name, $non_default_value);
|
||||
opts.debugging_opts.$name = $non_default_value;
|
||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||
assert_same_hash(&reference, &opts);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -471,7 +483,7 @@ fn test_debugging_options_tracking_hash() {
|
|||
untracked!(ast_json, true);
|
||||
untracked!(ast_json_noexpand, true);
|
||||
untracked!(borrowck, String::from("other"));
|
||||
untracked!(deduplicate_diagnostics, true);
|
||||
untracked!(deduplicate_diagnostics, false);
|
||||
untracked!(dep_tasks, true);
|
||||
untracked!(dont_buffer_diagnostics, true);
|
||||
untracked!(dump_dep_graph, true);
|
||||
|
@ -515,7 +527,7 @@ fn test_debugging_options_tracking_hash() {
|
|||
untracked!(self_profile_events, Some(vec![String::new()]));
|
||||
untracked!(span_debug, true);
|
||||
untracked!(span_free_formats, true);
|
||||
untracked!(strip, Strip::None);
|
||||
untracked!(strip, Strip::Debuginfo);
|
||||
untracked!(terminal_width, Some(80));
|
||||
untracked!(threads, 99);
|
||||
untracked!(time, true);
|
||||
|
@ -532,8 +544,9 @@ fn test_debugging_options_tracking_hash() {
|
|||
macro_rules! tracked {
|
||||
($name: ident, $non_default_value: expr) => {
|
||||
opts = reference.clone();
|
||||
assert_ne!(opts.debugging_opts.$name, $non_default_value);
|
||||
opts.debugging_opts.$name = $non_default_value;
|
||||
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||
assert_different_hash(&reference, &opts);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1617,7 +1617,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
.map(Path::new)
|
||||
.filter(|_| {
|
||||
// Only spend time on further checks if we have what to translate *to*.
|
||||
sess.real_rust_source_base_dir.is_some()
|
||||
sess.opts.real_rust_source_base_dir.is_some()
|
||||
})
|
||||
.filter(|virtual_dir| {
|
||||
// Don't translate away `/rustc/$hash` if we're still remapping to it,
|
||||
|
@ -1629,11 +1629,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
debug!(
|
||||
"try_to_translate_virtual_to_real(name={:?}): \
|
||||
virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
|
||||
name, virtual_rust_source_base_dir, sess.real_rust_source_base_dir,
|
||||
name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
|
||||
);
|
||||
|
||||
if let Some(virtual_dir) = virtual_rust_source_base_dir {
|
||||
if let Some(real_dir) = &sess.real_rust_source_base_dir {
|
||||
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::Named(one_path) = old_name {
|
||||
if let Ok(rest) = one_path.strip_prefix(virtual_dir) {
|
||||
|
|
|
@ -943,7 +943,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe
|
|||
intravisit::walk_crate(&mut collector, tcx.untracked_crate);
|
||||
|
||||
let crate_disambiguator = tcx.sess.local_crate_disambiguator();
|
||||
let cmdline_args = tcx.sess.opts.dep_tracking_hash();
|
||||
let cmdline_args = tcx.sess.opts.dep_tracking_hash(true);
|
||||
collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args)
|
||||
};
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ pub enum InstrumentCoverage {
|
|||
Off,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Clone, PartialEq, Hash, Debug)]
|
||||
pub enum LinkerPluginLto {
|
||||
LinkerPlugin(PathBuf),
|
||||
LinkerPluginAuto,
|
||||
|
@ -172,7 +172,7 @@ impl LinkerPluginLto {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Clone, PartialEq, Hash, Debug)]
|
||||
pub enum SwitchWithOptPath {
|
||||
Enabled(Option<PathBuf>),
|
||||
Disabled,
|
||||
|
@ -702,6 +702,7 @@ impl Default for Options {
|
|||
cli_forced_codegen_units: None,
|
||||
cli_forced_thinlto_off: false,
|
||||
remap_path_prefix: Vec::new(),
|
||||
real_rust_source_base_dir: None,
|
||||
edition: DEFAULT_EDITION,
|
||||
json_artifact_notifications: false,
|
||||
json_unused_externs: false,
|
||||
|
@ -778,7 +779,7 @@ pub enum CrateType {
|
|||
|
||||
impl_stable_hash_via_hash!(CrateType);
|
||||
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
|
||||
pub enum Passes {
|
||||
Some(Vec<String>),
|
||||
All,
|
||||
|
@ -1980,6 +1981,34 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
}
|
||||
}
|
||||
|
||||
// Try to find a directory containing the Rust `src`, for more details see
|
||||
// the doc comment on the `real_rust_source_base_dir` field.
|
||||
let tmp_buf;
|
||||
let sysroot = match &sysroot_opt {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
tmp_buf = crate::filesearch::get_or_default_sysroot();
|
||||
&tmp_buf
|
||||
}
|
||||
};
|
||||
let real_rust_source_base_dir = {
|
||||
// This is the location used by the `rust-src` `rustup` component.
|
||||
let mut candidate = sysroot.join("lib/rustlib/src/rust");
|
||||
if let Ok(metadata) = candidate.symlink_metadata() {
|
||||
// Replace the symlink rustbuild creates, with its destination.
|
||||
// We could try to use `fs::canonicalize` instead, but that might
|
||||
// produce unnecessarily verbose path.
|
||||
if metadata.file_type().is_symlink() {
|
||||
if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
|
||||
candidate = symlink_dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only use this directory if it has a file we can expect to always find.
|
||||
if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
|
||||
};
|
||||
|
||||
Options {
|
||||
crate_types,
|
||||
optimize: opt_level,
|
||||
|
@ -2010,6 +2039,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|||
cli_forced_codegen_units: codegen_units,
|
||||
cli_forced_thinlto_off: disable_thinlto,
|
||||
remap_path_prefix,
|
||||
real_rust_source_base_dir,
|
||||
edition,
|
||||
json_artifact_notifications,
|
||||
json_unused_externs,
|
||||
|
@ -2374,6 +2404,7 @@ crate mod dep_tracking {
|
|||
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!(String);
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!((PathBuf, PathBuf));
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind));
|
||||
|
|
|
@ -20,73 +20,112 @@ use std::num::NonZeroUsize;
|
|||
use std::path::PathBuf;
|
||||
use std::str;
|
||||
|
||||
macro_rules! hash_option {
|
||||
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => {{}};
|
||||
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => {{
|
||||
macro_rules! insert {
|
||||
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => {
|
||||
if $sub_hashes
|
||||
.insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash)
|
||||
.is_some()
|
||||
{
|
||||
panic!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! hash_opt {
|
||||
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [UNTRACKED]) => {{}};
|
||||
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [TRACKED]) => {{ insert!($opt_name, $opt_expr, $sub_hashes) }};
|
||||
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $for_crate_hash: ident, [TRACKED_NO_CRATE_HASH]) => {{
|
||||
if !$for_crate_hash {
|
||||
insert!($opt_name, $opt_expr, $sub_hashes)
|
||||
}
|
||||
}};
|
||||
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [SUBSTRUCT]) => {{}};
|
||||
}
|
||||
|
||||
macro_rules! hash_substruct {
|
||||
($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [UNTRACKED]) => {{}};
|
||||
($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED]) => {{}};
|
||||
($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED_NO_CRATE_HASH]) => {{}};
|
||||
($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [SUBSTRUCT]) => {
|
||||
use crate::config::dep_tracking::DepTrackingHash;
|
||||
$opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash($hasher, $error_format);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! top_level_options {
|
||||
(pub struct Options { $(
|
||||
$opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*],
|
||||
( $( #[$top_level_attr:meta] )* pub struct Options { $(
|
||||
$( #[$attr:meta] )*
|
||||
$opt:ident : $t:ty [$dep_tracking_marker:ident],
|
||||
)* } ) => (
|
||||
#[derive(Clone)]
|
||||
$( #[$top_level_attr] )*
|
||||
pub struct Options {
|
||||
$(pub $opt: $t),*
|
||||
$(
|
||||
$( #[$attr] )*
|
||||
pub $opt: $t
|
||||
),*
|
||||
}
|
||||
|
||||
impl Options {
|
||||
pub fn dep_tracking_hash(&self) -> u64 {
|
||||
pub fn dep_tracking_hash(&self, for_crate_hash: bool) -> u64 {
|
||||
let mut sub_hashes = BTreeMap::new();
|
||||
$({
|
||||
hash_option!($opt,
|
||||
&self.$opt,
|
||||
&mut sub_hashes,
|
||||
[$dep_tracking_marker $($warn_val,
|
||||
$warn_text,
|
||||
self.error_format)*]);
|
||||
hash_opt!($opt,
|
||||
&self.$opt,
|
||||
&mut sub_hashes,
|
||||
for_crate_hash,
|
||||
[$dep_tracking_marker]);
|
||||
})*
|
||||
let mut hasher = DefaultHasher::new();
|
||||
dep_tracking::stable_hash(sub_hashes,
|
||||
&mut hasher,
|
||||
self.error_format);
|
||||
$({
|
||||
hash_substruct!($opt,
|
||||
&self.$opt,
|
||||
self.error_format,
|
||||
for_crate_hash,
|
||||
&mut hasher,
|
||||
[$dep_tracking_marker]);
|
||||
})*
|
||||
hasher.finish()
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// The top-level command-line options struct.
|
||||
//
|
||||
// For each option, one has to specify how it behaves with regard to the
|
||||
// dependency tracking system of incremental compilation. This is done via the
|
||||
// square-bracketed directive after the field type. The options are:
|
||||
//
|
||||
// [TRACKED]
|
||||
// A change in the given field will cause the compiler to completely clear the
|
||||
// incremental compilation cache before proceeding.
|
||||
//
|
||||
// [UNTRACKED]
|
||||
// Incremental compilation is not influenced by this option.
|
||||
//
|
||||
// If you add a new option to this struct or one of the sub-structs like
|
||||
// `CodegenOptions`, think about how it influences incremental compilation. If in
|
||||
// doubt, specify [TRACKED], which is always "correct" but might lead to
|
||||
// unnecessary re-compilation.
|
||||
top_level_options!(
|
||||
/// The top-level command-line options struct.
|
||||
///
|
||||
/// For each option, one has to specify how it behaves with regard to the
|
||||
/// dependency tracking system of incremental compilation. This is done via the
|
||||
/// square-bracketed directive after the field type. The options are:
|
||||
///
|
||||
/// - `[TRACKED]`
|
||||
/// A change in the given field will cause the compiler to completely clear the
|
||||
/// incremental compilation cache before proceeding.
|
||||
///
|
||||
/// - `[TRACKED_NO_CRATE_HASH]`
|
||||
/// Same as `[TRACKED]`, but will not affect the crate hash. This is useful for options that only
|
||||
/// affect the incremental cache.
|
||||
///
|
||||
/// - `[UNTRACKED]`
|
||||
/// Incremental compilation is not influenced by this option.
|
||||
///
|
||||
/// - `[SUBSTRUCT]`
|
||||
/// Second-level sub-structs containing more options.
|
||||
///
|
||||
/// If you add a new option to this struct or one of the sub-structs like
|
||||
/// `CodegenOptions`, think about how it influences incremental compilation. If in
|
||||
/// doubt, specify `[TRACKED]`, which is always "correct" but might lead to
|
||||
/// unnecessary re-compilation.
|
||||
pub struct Options {
|
||||
// The crate config requested for the session, which may be combined
|
||||
// with additional crate configurations during the compile process.
|
||||
/// The crate config requested for the session, which may be combined
|
||||
/// with additional crate configurations during the compile process.
|
||||
crate_types: Vec<CrateType> [TRACKED],
|
||||
optimize: OptLevel [TRACKED],
|
||||
// Include the `debug_assertions` flag in dependency tracking, since it
|
||||
// can influence whether overflow checks are done or not.
|
||||
/// Include the `debug_assertions` flag in dependency tracking, since it
|
||||
/// can influence whether overflow checks are done or not.
|
||||
debug_assertions: bool [TRACKED],
|
||||
debuginfo: DebugInfo [TRACKED],
|
||||
lint_opts: Vec<(String, lint::Level)> [TRACKED],
|
||||
|
@ -102,52 +141,60 @@ top_level_options!(
|
|||
test: bool [TRACKED],
|
||||
error_format: ErrorOutputType [UNTRACKED],
|
||||
|
||||
// If `Some`, enable incremental compilation, using the given
|
||||
// directory to store intermediate results.
|
||||
/// If `Some`, enable incremental compilation, using the given
|
||||
/// directory to store intermediate results.
|
||||
incremental: Option<PathBuf> [UNTRACKED],
|
||||
|
||||
debugging_opts: DebuggingOptions [TRACKED],
|
||||
debugging_opts: DebuggingOptions [SUBSTRUCT],
|
||||
prints: Vec<PrintRequest> [UNTRACKED],
|
||||
// Determines which borrow checker(s) to run. This is the parsed, sanitized
|
||||
// version of `debugging_opts.borrowck`, which is just a plain string.
|
||||
/// Determines which borrow checker(s) to run. This is the parsed, sanitized
|
||||
/// version of `debugging_opts.borrowck`, which is just a plain string.
|
||||
borrowck_mode: BorrowckMode [UNTRACKED],
|
||||
cg: CodegenOptions [TRACKED],
|
||||
cg: CodegenOptions [SUBSTRUCT],
|
||||
externs: Externs [UNTRACKED],
|
||||
extern_dep_specs: ExternDepSpecs [UNTRACKED],
|
||||
crate_name: Option<String> [TRACKED],
|
||||
// An optional name to use as the crate for std during std injection,
|
||||
// written `extern crate name as std`. Defaults to `std`. Used by
|
||||
// out-of-tree drivers.
|
||||
/// An optional name to use as the crate for std during std injection,
|
||||
/// written `extern crate name as std`. Defaults to `std`. Used by
|
||||
/// out-of-tree drivers.
|
||||
alt_std_name: Option<String> [TRACKED],
|
||||
// Indicates how the compiler should treat unstable features.
|
||||
/// Indicates how the compiler should treat unstable features.
|
||||
unstable_features: UnstableFeatures [TRACKED],
|
||||
|
||||
// Indicates whether this run of the compiler is actually rustdoc. This
|
||||
// is currently just a hack and will be removed eventually, so please
|
||||
// try to not rely on this too much.
|
||||
/// Indicates whether this run of the compiler is actually rustdoc. This
|
||||
/// is currently just a hack and will be removed eventually, so please
|
||||
/// try to not rely on this too much.
|
||||
actually_rustdoc: bool [TRACKED],
|
||||
|
||||
// Control path trimming.
|
||||
/// Control path trimming.
|
||||
trimmed_def_paths: TrimmedDefPaths [TRACKED],
|
||||
|
||||
// Specifications of codegen units / ThinLTO which are forced as a
|
||||
// result of parsing command line options. These are not necessarily
|
||||
// what rustc was invoked with, but massaged a bit to agree with
|
||||
// commands like `--emit llvm-ir` which they're often incompatible with
|
||||
// if we otherwise use the defaults of rustc.
|
||||
/// Specifications of codegen units / ThinLTO which are forced as a
|
||||
/// result of parsing command line options. These are not necessarily
|
||||
/// what rustc was invoked with, but massaged a bit to agree with
|
||||
/// commands like `--emit llvm-ir` which they're often incompatible with
|
||||
/// if we otherwise use the defaults of rustc.
|
||||
cli_forced_codegen_units: Option<usize> [UNTRACKED],
|
||||
cli_forced_thinlto_off: bool [UNTRACKED],
|
||||
|
||||
// Remap source path prefixes in all output (messages, object files, debug, etc.).
|
||||
remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
|
||||
/// Remap source path prefixes in all output (messages, object files, debug, etc.).
|
||||
remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
|
||||
/// Base directory containing the `src/` for the Rust standard library, and
|
||||
/// potentially `rustc` as well, if we can can find it. Right now it's always
|
||||
/// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
|
||||
///
|
||||
/// This directory is what the virtual `/rustc/$hash` is translated back to,
|
||||
/// if Rust was built with path remapping to `/rustc/$hash` enabled
|
||||
/// (the `rust.remap-debuginfo` option in `config.toml`).
|
||||
real_rust_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
|
||||
|
||||
edition: Edition [TRACKED],
|
||||
|
||||
// `true` if we're emitting JSON blobs about each artifact produced
|
||||
// by the compiler.
|
||||
/// `true` if we're emitting JSON blobs about each artifact produced
|
||||
/// by the compiler.
|
||||
json_artifact_notifications: bool [TRACKED],
|
||||
|
||||
// `true` if we're emitting a JSON blob containing the unused externs
|
||||
/// `true` if we're emitting a JSON blob containing the unused externs
|
||||
json_unused_externs: bool [UNTRACKED],
|
||||
|
||||
pretty: Option<PpMode> [UNTRACKED],
|
||||
|
@ -166,10 +213,10 @@ macro_rules! options {
|
|||
($struct_name:ident, $setter_name:ident, $defaultfn:ident,
|
||||
$buildfn:ident, $prefix:expr, $outputname:expr,
|
||||
$stat:ident, $mod_desc:ident, $mod_set:ident,
|
||||
$($opt:ident : $t:ty = (
|
||||
$($( #[$attr:meta] )* $opt:ident : $t:ty = (
|
||||
$init:expr,
|
||||
$parse:ident,
|
||||
[$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*],
|
||||
[$dep_tracking_marker:ident],
|
||||
$desc:expr)
|
||||
),* ,) =>
|
||||
(
|
||||
|
@ -177,7 +224,7 @@ macro_rules! options {
|
|||
pub struct $struct_name { $(pub $opt: $t),* }
|
||||
|
||||
pub fn $defaultfn() -> $struct_name {
|
||||
$struct_name { $($opt: $init),* }
|
||||
$struct_name { $( $( #[$attr] )* $opt: $init),* }
|
||||
}
|
||||
|
||||
pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name
|
||||
|
@ -219,18 +266,21 @@ macro_rules! options {
|
|||
return op;
|
||||
}
|
||||
|
||||
impl dep_tracking::DepTrackingHash for $struct_name {
|
||||
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
|
||||
impl $struct_name {
|
||||
fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
|
||||
let mut sub_hashes = BTreeMap::new();
|
||||
$({
|
||||
hash_option!($opt,
|
||||
&self.$opt,
|
||||
&mut sub_hashes,
|
||||
[$dep_tracking_marker $($dep_warn_val,
|
||||
$dep_warn_text,
|
||||
error_format)*]);
|
||||
hash_opt!($opt,
|
||||
&self.$opt,
|
||||
&mut sub_hashes,
|
||||
_for_crate_hash,
|
||||
[$dep_tracking_marker]);
|
||||
})*
|
||||
dep_tracking::stable_hash(sub_hashes, hasher, error_format);
|
||||
let mut hasher = DefaultHasher::new();
|
||||
dep_tracking::stable_hash(sub_hashes,
|
||||
&mut hasher,
|
||||
error_format);
|
||||
hasher.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1128,7 +1178,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
|
||||
parse_switch_with_opt_path, [UNTRACKED],
|
||||
"run the self profiler and output the raw event data"),
|
||||
// keep this in sync with the event filter names in librustc_data_structures/profiling.rs
|
||||
/// keep this in sync with the event filter names in librustc_data_structures/profiling.rs
|
||||
self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
|
||||
"specify the events recorded by the self profiler;
|
||||
for example: `-Z self-profile-events=default,query-keys`
|
||||
|
@ -1140,7 +1190,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"show spans for compiler debugging (expr|pat|ty)"),
|
||||
span_debug: bool = (false, parse_bool, [UNTRACKED],
|
||||
"forward proc_macro::Span's `Debug` impl to `Span`"),
|
||||
// o/w tests have closure@path
|
||||
/// o/w tests have closure@path
|
||||
span_free_formats: bool = (false, parse_bool, [UNTRACKED],
|
||||
"exclude spans when debug-printing compiler state (default: no)"),
|
||||
src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED],
|
||||
|
@ -1161,10 +1211,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"select processor to schedule for (`rustc --print target-cpus` for details)"),
|
||||
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"enable ThinLTO when possible"),
|
||||
// We default to 1 here since we want to behave like
|
||||
// a sequential compiler for now. This'll likely be adjusted
|
||||
// in the future. Note that -Zthreads=0 is the way to get
|
||||
// the num_cpus behavior.
|
||||
/// We default to 1 here since we want to behave like
|
||||
/// a sequential compiler for now. This'll likely be adjusted
|
||||
/// in the future. Note that -Zthreads=0 is the way to get
|
||||
/// the num_cpus behavior.
|
||||
threads: usize = (1, parse_threads, [UNTRACKED],
|
||||
"use a thread pool with N threads"),
|
||||
time: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -1220,7 +1270,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
// - compiler/rustc_interface/src/tests.rs
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
||||
pub enum WasiExecModel {
|
||||
Command,
|
||||
Reactor,
|
||||
|
|
|
@ -214,15 +214,6 @@ pub struct Session {
|
|||
/// drown everything else in noise.
|
||||
miri_unleashed_features: Lock<Vec<(Span, Option<Symbol>)>>,
|
||||
|
||||
/// Base directory containing the `src/` for the Rust standard library, and
|
||||
/// potentially `rustc` as well, if we can can find it. Right now it's always
|
||||
/// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
|
||||
///
|
||||
/// This directory is what the virtual `/rustc/$hash` is translated back to,
|
||||
/// if Rust was built with path remapping to `/rustc/$hash` enabled
|
||||
/// (the `rust.remap-debuginfo` option in `config.toml`).
|
||||
pub real_rust_source_base_dir: Option<PathBuf>,
|
||||
|
||||
/// Architecture to use for interpreting asm!.
|
||||
pub asm_arch: Option<InlineAsmArch>,
|
||||
|
||||
|
@ -1390,26 +1381,6 @@ pub fn build_session(
|
|||
_ => CtfeBacktrace::Disabled,
|
||||
});
|
||||
|
||||
// Try to find a directory containing the Rust `src`, for more details see
|
||||
// the doc comment on the `real_rust_source_base_dir` field.
|
||||
let real_rust_source_base_dir = {
|
||||
// This is the location used by the `rust-src` `rustup` component.
|
||||
let mut candidate = sysroot.join("lib/rustlib/src/rust");
|
||||
if let Ok(metadata) = candidate.symlink_metadata() {
|
||||
// Replace the symlink rustbuild creates, with its destination.
|
||||
// We could try to use `fs::canonicalize` instead, but that might
|
||||
// produce unnecessarily verbose path.
|
||||
if metadata.file_type().is_symlink() {
|
||||
if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
|
||||
candidate = symlink_dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only use this directory if it has a file we can expect to always find.
|
||||
if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
|
||||
};
|
||||
|
||||
let asm_arch =
|
||||
if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None };
|
||||
|
||||
|
@ -1453,7 +1424,6 @@ pub fn build_session(
|
|||
system_library_path: OneThread::new(RefCell::new(Default::default())),
|
||||
ctfe_backtrace,
|
||||
miri_unleashed_features: Lock::new(Default::default()),
|
||||
real_rust_source_base_dir,
|
||||
asm_arch,
|
||||
target_features: FxHashSet::default(),
|
||||
known_attrs: Lock::new(MarkedAttrs::new()),
|
||||
|
|
|
@ -2,20 +2,23 @@
|
|||
// the cache while changing an untracked one doesn't.
|
||||
|
||||
// ignore-asmjs wasm2js does not support source maps yet
|
||||
// revisions:rpass1 rpass2 rpass3
|
||||
// revisions:rpass1 rpass2 rpass3 rpass4
|
||||
// compile-flags: -Z query-dep-graph
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#![rustc_partition_codegened(module="commandline_args", cfg="rpass2")]
|
||||
#![rustc_partition_reused(module="commandline_args", cfg="rpass3")]
|
||||
#![rustc_partition_codegened(module="commandline_args", cfg="rpass4")]
|
||||
|
||||
// Between revisions 1 and 2, we are changing the debuginfo-level, which should
|
||||
// invalidate the cache. Between revisions 2 and 3, we are adding `--verbose`
|
||||
// which should have no effect on the cache:
|
||||
// which should have no effect on the cache. Between revisions, we are adding
|
||||
// `--remap-path-prefix` which should invalidate the cache:
|
||||
//[rpass1] compile-flags: -C debuginfo=0
|
||||
//[rpass2] compile-flags: -C debuginfo=2
|
||||
//[rpass3] compile-flags: -C debuginfo=2 --verbose
|
||||
//[rpass4] compile-flags: -C debuginfo=2 --verbose --remap-path-prefix=/home/bors/rust=src
|
||||
|
||||
pub fn main() {
|
||||
// empty
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
-include ../tools.mk
|
||||
|
||||
# rust-lang/rust#70924: Test that if we add rust-src component in between two
|
||||
# incremetnal compiles, the compiler does not ICE on the second.
|
||||
# incremental compiles, the compiler does not ICE on the second.
|
||||
|
||||
# This test uses `ln -s` rather than copying to save testing time, but its
|
||||
# usage doesn't work on windows. So ignore windows.
|
||||
|
|
Loading…
Reference in New Issue