1
Fork 0

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:
bors 2021-04-29 14:57:17 +00:00
commit 814a560072
10 changed files with 251 additions and 184 deletions

View file

@ -104,7 +104,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
// Fortunately, we just checked that this isn't the case. // Fortunately, we just checked that this isn't the case.
let path = dep_graph_path_from(&sess.incr_comp_session_dir()); let path = dep_graph_path_from(&sess.incr_comp_session_dir());
let report_incremental_info = sess.opts.debugging_opts.incremental_info; 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 mut prev_work_products = FxHashMap::default();
let nightly_build = sess.is_nightly_build(); let nightly_build = sess.is_nightly_build();

View file

@ -219,7 +219,7 @@ pub fn build_dep_graph(
} }
// First encode the commandline arguments hash // 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!( sess.err(&format!(
"failed to write dependency graph hash `{}`: {}", "failed to write dependency graph hash `{}`: {}",
path_buf.display(), path_buf.display(),

View file

@ -19,6 +19,7 @@ use rustc_span::symbol::sym;
use rustc_span::SourceFileHashAlgorithm; use rustc_span::SourceFileHashAlgorithm;
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel}; use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel};
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator; use std::iter::FromIterator;
use std::num::NonZeroUsize; 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()) 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 // When the user supplies --test we should implicitly supply --cfg test
#[test] #[test]
fn test_switch_implies_cfg_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")))]); v2.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]);
v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); assert_different_hash(&v1, &v2);
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); assert_different_hash(&v1, &v3);
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); assert_different_hash(&v2, &v3);
// 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());
} }
#[test] #[test]
@ -155,10 +172,7 @@ fn test_output_types_tracking_hash_different_construction_order() {
(OutputType::Exe, Some(PathBuf::from("./some/thing"))), (OutputType::Exe, Some(PathBuf::from("./some/thing"))),
]); ]);
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); assert_same_hash(&v1, &v2);
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
} }
#[test] #[test]
@ -182,14 +196,9 @@ fn test_externs_tracking_hash_different_construction_order() {
(String::from("d"), new_public_extern_entry(vec!["f", "e"])), (String::from("d"), new_public_extern_entry(vec!["f", "e"])),
])); ]));
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); assert_same_hash(&v1, &v2);
assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash()); assert_same_hash(&v1, &v3);
assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash()); assert_same_hash(&v2, &v3);
// 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());
} }
#[test] #[test]
@ -219,14 +228,9 @@ fn test_lints_tracking_hash_different_values() {
(String::from("d"), Level::Deny), (String::from("d"), Level::Deny),
]; ];
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); assert_different_hash(&v1, &v2);
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); assert_different_hash(&v1, &v3);
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash()); assert_different_hash(&v2, &v3);
// 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());
} }
#[test] #[test]
@ -248,11 +252,7 @@ fn test_lints_tracking_hash_different_construction_order() {
(String::from("d"), Level::Forbid), (String::from("d"), Level::Forbid),
]; ];
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash()); assert_same_hash(&v1, &v2);
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
} }
#[test] #[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("dependency=ghi", JSON));
v4.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON)); v4.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON));
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); assert_same_hash(&v1, &v2);
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); assert_same_hash(&v1, &v3);
assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash()); assert_same_hash(&v1, &v4);
// 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());
} }
#[test] #[test]
@ -338,15 +332,9 @@ fn test_native_libs_tracking_hash_different_values() {
(String::from("c"), None, NativeLibKind::Unspecified), (String::from("c"), None, NativeLibKind::Unspecified),
]; ];
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash()); assert_different_hash(&v1, &v2);
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash()); assert_different_hash(&v1, &v3);
assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash()); assert_different_hash(&v1, &v4);
// 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());
} }
#[test] #[test]
@ -374,14 +362,9 @@ fn test_native_libs_tracking_hash_different_order() {
(String::from("b"), None, NativeLibKind::Framework), (String::from("b"), None, NativeLibKind::Framework),
]; ];
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); assert_same_hash(&v1, &v2);
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); assert_same_hash(&v1, &v3);
assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash()); assert_same_hash(&v2, &v3);
// 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());
} }
#[test] #[test]
@ -391,8 +374,9 @@ fn test_codegen_options_tracking_hash() {
macro_rules! untracked { macro_rules! untracked {
($name: ident, $non_default_value: expr) => { ($name: ident, $non_default_value: expr) => {
assert_ne!(opts.cg.$name, $non_default_value);
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 { macro_rules! tracked {
($name: ident, $non_default_value: expr) => { ($name: ident, $non_default_value: expr) => {
opts = reference.clone(); opts = reference.clone();
assert_ne!(opts.cg.$name, $non_default_value);
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")); 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] #[test]
fn test_debugging_options_tracking_hash() { fn test_debugging_options_tracking_hash() {
let reference = Options::default(); let reference = Options::default();
@ -461,8 +472,9 @@ fn test_debugging_options_tracking_hash() {
macro_rules! untracked { macro_rules! untracked {
($name: ident, $non_default_value: expr) => { ($name: ident, $non_default_value: expr) => {
assert_ne!(opts.debugging_opts.$name, $non_default_value);
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, true);
untracked!(ast_json_noexpand, true); untracked!(ast_json_noexpand, true);
untracked!(borrowck, String::from("other")); untracked!(borrowck, String::from("other"));
untracked!(deduplicate_diagnostics, true); untracked!(deduplicate_diagnostics, false);
untracked!(dep_tasks, true); untracked!(dep_tasks, true);
untracked!(dont_buffer_diagnostics, true); untracked!(dont_buffer_diagnostics, true);
untracked!(dump_dep_graph, 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!(self_profile_events, Some(vec![String::new()]));
untracked!(span_debug, true); untracked!(span_debug, true);
untracked!(span_free_formats, true); untracked!(span_free_formats, true);
untracked!(strip, Strip::None); untracked!(strip, Strip::Debuginfo);
untracked!(terminal_width, Some(80)); untracked!(terminal_width, Some(80));
untracked!(threads, 99); untracked!(threads, 99);
untracked!(time, true); untracked!(time, true);
@ -532,8 +544,9 @@ fn test_debugging_options_tracking_hash() {
macro_rules! tracked { macro_rules! tracked {
($name: ident, $non_default_value: expr) => { ($name: ident, $non_default_value: expr) => {
opts = reference.clone(); opts = reference.clone();
assert_ne!(opts.debugging_opts.$name, $non_default_value);
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);
}; };
} }

View file

@ -1617,7 +1617,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.map(Path::new) .map(Path::new)
.filter(|_| { .filter(|_| {
// Only spend time on further checks if we have what to translate *to*. // 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| { .filter(|virtual_dir| {
// Don't translate away `/rustc/$hash` if we're still remapping to it, // Don't translate away `/rustc/$hash` if we're still remapping to it,
@ -1629,11 +1629,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
debug!( debug!(
"try_to_translate_virtual_to_real(name={:?}): \ "try_to_translate_virtual_to_real(name={:?}): \
virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}", 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(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::FileName::Real(old_name) = name {
if let rustc_span::RealFileName::Named(one_path) = old_name { if let rustc_span::RealFileName::Named(one_path) = old_name {
if let Ok(rest) = one_path.strip_prefix(virtual_dir) { if let Ok(rest) = one_path.strip_prefix(virtual_dir) {

View file

@ -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); intravisit::walk_crate(&mut collector, tcx.untracked_crate);
let crate_disambiguator = tcx.sess.local_crate_disambiguator(); 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) collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args)
}; };

View file

@ -156,7 +156,7 @@ pub enum InstrumentCoverage {
Off, Off,
} }
#[derive(Clone, PartialEq, Hash)] #[derive(Clone, PartialEq, Hash, Debug)]
pub enum LinkerPluginLto { pub enum LinkerPluginLto {
LinkerPlugin(PathBuf), LinkerPlugin(PathBuf),
LinkerPluginAuto, LinkerPluginAuto,
@ -172,7 +172,7 @@ impl LinkerPluginLto {
} }
} }
#[derive(Clone, PartialEq, Hash)] #[derive(Clone, PartialEq, Hash, Debug)]
pub enum SwitchWithOptPath { pub enum SwitchWithOptPath {
Enabled(Option<PathBuf>), Enabled(Option<PathBuf>),
Disabled, Disabled,
@ -702,6 +702,7 @@ impl Default for Options {
cli_forced_codegen_units: None, cli_forced_codegen_units: None,
cli_forced_thinlto_off: false, cli_forced_thinlto_off: false,
remap_path_prefix: Vec::new(), remap_path_prefix: Vec::new(),
real_rust_source_base_dir: None,
edition: DEFAULT_EDITION, edition: DEFAULT_EDITION,
json_artifact_notifications: false, json_artifact_notifications: false,
json_unused_externs: false, json_unused_externs: false,
@ -778,7 +779,7 @@ pub enum CrateType {
impl_stable_hash_via_hash!(CrateType); impl_stable_hash_via_hash!(CrateType);
#[derive(Clone, Hash)] #[derive(Clone, Hash, Debug, PartialEq, Eq)]
pub enum Passes { pub enum Passes {
Some(Vec<String>), Some(Vec<String>),
All, 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 { Options {
crate_types, crate_types,
optimize: opt_level, optimize: opt_level,
@ -2010,6 +2039,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
cli_forced_codegen_units: codegen_units, cli_forced_codegen_units: codegen_units,
cli_forced_thinlto_off: disable_thinlto, cli_forced_thinlto_off: disable_thinlto,
remap_path_prefix, remap_path_prefix,
real_rust_source_base_dir,
edition, edition,
json_artifact_notifications, json_artifact_notifications,
json_unused_externs, 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!(String);
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); 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!(CrateType);
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level)); impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind)); impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind));

View file

@ -20,73 +20,112 @@ use std::num::NonZeroUsize;
use std::path::PathBuf; use std::path::PathBuf;
use std::str; use std::str;
macro_rules! hash_option { macro_rules! insert {
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => {{}}; ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => {
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => {{
if $sub_hashes if $sub_hashes
.insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash) .insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash)
.is_some() .is_some()
{ {
panic!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name)) 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 { macro_rules! top_level_options {
(pub struct Options { $( ( $( #[$top_level_attr:meta] )* pub struct Options { $(
$opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*], $( #[$attr:meta] )*
$opt:ident : $t:ty [$dep_tracking_marker:ident],
)* } ) => ( )* } ) => (
#[derive(Clone)] #[derive(Clone)]
$( #[$top_level_attr] )*
pub struct Options { pub struct Options {
$(pub $opt: $t),* $(
$( #[$attr] )*
pub $opt: $t
),*
} }
impl Options { 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(); let mut sub_hashes = BTreeMap::new();
$({ $({
hash_option!($opt, hash_opt!($opt,
&self.$opt, &self.$opt,
&mut sub_hashes, &mut sub_hashes,
[$dep_tracking_marker $($warn_val, for_crate_hash,
$warn_text, [$dep_tracking_marker]);
self.error_format)*]);
})* })*
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
dep_tracking::stable_hash(sub_hashes, dep_tracking::stable_hash(sub_hashes,
&mut hasher, &mut hasher,
self.error_format); self.error_format);
$({
hash_substruct!($opt,
&self.$opt,
self.error_format,
for_crate_hash,
&mut hasher,
[$dep_tracking_marker]);
})*
hasher.finish() 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!( 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 { pub struct Options {
// The crate config requested for the session, which may be combined /// The crate config requested for the session, which may be combined
// with additional crate configurations during the compile process. /// with additional crate configurations during the compile process.
crate_types: Vec<CrateType> [TRACKED], crate_types: Vec<CrateType> [TRACKED],
optimize: OptLevel [TRACKED], optimize: OptLevel [TRACKED],
// Include the `debug_assertions` flag in dependency tracking, since it /// Include the `debug_assertions` flag in dependency tracking, since it
// can influence whether overflow checks are done or not. /// can influence whether overflow checks are done or not.
debug_assertions: bool [TRACKED], debug_assertions: bool [TRACKED],
debuginfo: DebugInfo [TRACKED], debuginfo: DebugInfo [TRACKED],
lint_opts: Vec<(String, lint::Level)> [TRACKED], lint_opts: Vec<(String, lint::Level)> [TRACKED],
@ -102,52 +141,60 @@ top_level_options!(
test: bool [TRACKED], test: bool [TRACKED],
error_format: ErrorOutputType [UNTRACKED], error_format: ErrorOutputType [UNTRACKED],
// If `Some`, enable incremental compilation, using the given /// If `Some`, enable incremental compilation, using the given
// directory to store intermediate results. /// directory to store intermediate results.
incremental: Option<PathBuf> [UNTRACKED], incremental: Option<PathBuf> [UNTRACKED],
debugging_opts: DebuggingOptions [TRACKED], debugging_opts: DebuggingOptions [SUBSTRUCT],
prints: Vec<PrintRequest> [UNTRACKED], prints: Vec<PrintRequest> [UNTRACKED],
// Determines which borrow checker(s) to run. This is the parsed, sanitized /// Determines which borrow checker(s) to run. This is the parsed, sanitized
// version of `debugging_opts.borrowck`, which is just a plain string. /// version of `debugging_opts.borrowck`, which is just a plain string.
borrowck_mode: BorrowckMode [UNTRACKED], borrowck_mode: BorrowckMode [UNTRACKED],
cg: CodegenOptions [TRACKED], cg: CodegenOptions [SUBSTRUCT],
externs: Externs [UNTRACKED], externs: Externs [UNTRACKED],
extern_dep_specs: ExternDepSpecs [UNTRACKED], extern_dep_specs: ExternDepSpecs [UNTRACKED],
crate_name: Option<String> [TRACKED], crate_name: Option<String> [TRACKED],
// An optional name to use as the crate for std during std injection, /// An optional name to use as the crate for std during std injection,
// written `extern crate name as std`. Defaults to `std`. Used by /// written `extern crate name as std`. Defaults to `std`. Used by
// out-of-tree drivers. /// out-of-tree drivers.
alt_std_name: Option<String> [TRACKED], 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], unstable_features: UnstableFeatures [TRACKED],
// Indicates whether this run of the compiler is actually rustdoc. This /// Indicates whether this run of the compiler is actually rustdoc. This
// is currently just a hack and will be removed eventually, so please /// is currently just a hack and will be removed eventually, so please
// try to not rely on this too much. /// try to not rely on this too much.
actually_rustdoc: bool [TRACKED], actually_rustdoc: bool [TRACKED],
// Control path trimming. /// Control path trimming.
trimmed_def_paths: TrimmedDefPaths [TRACKED], trimmed_def_paths: TrimmedDefPaths [TRACKED],
// Specifications of codegen units / ThinLTO which are forced as a /// Specifications of codegen units / ThinLTO which are forced as a
// result of parsing command line options. These are not necessarily /// result of parsing command line options. These are not necessarily
// what rustc was invoked with, but massaged a bit to agree with /// what rustc was invoked with, but massaged a bit to agree with
// commands like `--emit llvm-ir` which they're often incompatible with /// commands like `--emit llvm-ir` which they're often incompatible with
// if we otherwise use the defaults of rustc. /// if we otherwise use the defaults of rustc.
cli_forced_codegen_units: Option<usize> [UNTRACKED], cli_forced_codegen_units: Option<usize> [UNTRACKED],
cli_forced_thinlto_off: bool [UNTRACKED], cli_forced_thinlto_off: bool [UNTRACKED],
// Remap source path prefixes in all output (messages, object files, debug, etc.). /// Remap source path prefixes in all output (messages, object files, debug, etc.).
remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED], 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], edition: Edition [TRACKED],
// `true` if we're emitting JSON blobs about each artifact produced /// `true` if we're emitting JSON blobs about each artifact produced
// by the compiler. /// by the compiler.
json_artifact_notifications: bool [TRACKED], 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], json_unused_externs: bool [UNTRACKED],
pretty: Option<PpMode> [UNTRACKED], pretty: Option<PpMode> [UNTRACKED],
@ -166,10 +213,10 @@ macro_rules! options {
($struct_name:ident, $setter_name:ident, $defaultfn:ident, ($struct_name:ident, $setter_name:ident, $defaultfn:ident,
$buildfn:ident, $prefix:expr, $outputname:expr, $buildfn:ident, $prefix:expr, $outputname:expr,
$stat:ident, $mod_desc:ident, $mod_set:ident, $stat:ident, $mod_desc:ident, $mod_set:ident,
$($opt:ident : $t:ty = ( $($( #[$attr:meta] )* $opt:ident : $t:ty = (
$init:expr, $init:expr,
$parse:ident, $parse:ident,
[$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*], [$dep_tracking_marker:ident],
$desc:expr) $desc:expr)
),* ,) => ),* ,) =>
( (
@ -177,7 +224,7 @@ macro_rules! options {
pub struct $struct_name { $(pub $opt: $t),* } pub struct $struct_name { $(pub $opt: $t),* }
pub fn $defaultfn() -> $struct_name { 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 pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name
@ -219,18 +266,21 @@ macro_rules! options {
return op; return op;
} }
impl dep_tracking::DepTrackingHash for $struct_name { impl $struct_name {
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
let mut sub_hashes = BTreeMap::new(); let mut sub_hashes = BTreeMap::new();
$({ $({
hash_option!($opt, hash_opt!($opt,
&self.$opt, &self.$opt,
&mut sub_hashes, &mut sub_hashes,
[$dep_tracking_marker $($dep_warn_val, _for_crate_hash,
$dep_warn_text, [$dep_tracking_marker]);
error_format)*]);
})* })*
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, self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
parse_switch_with_opt_path, [UNTRACKED], parse_switch_with_opt_path, [UNTRACKED],
"run the self profiler and output the raw event data"), "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], self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
"specify the events recorded by the self profiler; "specify the events recorded by the self profiler;
for example: `-Z self-profile-events=default,query-keys` 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)"), "show spans for compiler debugging (expr|pat|ty)"),
span_debug: bool = (false, parse_bool, [UNTRACKED], span_debug: bool = (false, parse_bool, [UNTRACKED],
"forward proc_macro::Span's `Debug` impl to `Span`"), "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], span_free_formats: bool = (false, parse_bool, [UNTRACKED],
"exclude spans when debug-printing compiler state (default: no)"), "exclude spans when debug-printing compiler state (default: no)"),
src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED], 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)"), "select processor to schedule for (`rustc --print target-cpus` for details)"),
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED], thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable ThinLTO when possible"), "enable ThinLTO when possible"),
// We default to 1 here since we want to behave like /// We default to 1 here since we want to behave like
// a sequential compiler for now. This'll likely be adjusted /// a sequential compiler for now. This'll likely be adjusted
// in the future. Note that -Zthreads=0 is the way to get /// in the future. Note that -Zthreads=0 is the way to get
// the num_cpus behavior. /// the num_cpus behavior.
threads: usize = (1, parse_threads, [UNTRACKED], threads: usize = (1, parse_threads, [UNTRACKED],
"use a thread pool with N threads"), "use a thread pool with N threads"),
time: bool = (false, parse_bool, [UNTRACKED], time: bool = (false, parse_bool, [UNTRACKED],
@ -1220,7 +1270,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
// - compiler/rustc_interface/src/tests.rs // - compiler/rustc_interface/src/tests.rs
} }
#[derive(Clone, Hash)] #[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub enum WasiExecModel { pub enum WasiExecModel {
Command, Command,
Reactor, Reactor,

View file

@ -214,15 +214,6 @@ pub struct Session {
/// drown everything else in noise. /// drown everything else in noise.
miri_unleashed_features: Lock<Vec<(Span, Option<Symbol>)>>, 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!. /// Architecture to use for interpreting asm!.
pub asm_arch: Option<InlineAsmArch>, pub asm_arch: Option<InlineAsmArch>,
@ -1390,26 +1381,6 @@ pub fn build_session(
_ => CtfeBacktrace::Disabled, _ => 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 = let asm_arch =
if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None }; 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())), system_library_path: OneThread::new(RefCell::new(Default::default())),
ctfe_backtrace, ctfe_backtrace,
miri_unleashed_features: Lock::new(Default::default()), miri_unleashed_features: Lock::new(Default::default()),
real_rust_source_base_dir,
asm_arch, asm_arch,
target_features: FxHashSet::default(), target_features: FxHashSet::default(),
known_attrs: Lock::new(MarkedAttrs::new()), known_attrs: Lock::new(MarkedAttrs::new()),

View file

@ -2,20 +2,23 @@
// the cache while changing an untracked one doesn't. // the cache while changing an untracked one doesn't.
// ignore-asmjs wasm2js does not support source maps yet // ignore-asmjs wasm2js does not support source maps yet
// revisions:rpass1 rpass2 rpass3 // revisions:rpass1 rpass2 rpass3 rpass4
// compile-flags: -Z query-dep-graph // compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![rustc_partition_codegened(module="commandline_args", cfg="rpass2")] #![rustc_partition_codegened(module="commandline_args", cfg="rpass2")]
#![rustc_partition_reused(module="commandline_args", cfg="rpass3")] #![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 // 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` // 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 //[rpass1] compile-flags: -C debuginfo=0
//[rpass2] compile-flags: -C debuginfo=2 //[rpass2] compile-flags: -C debuginfo=2
//[rpass3] compile-flags: -C debuginfo=2 --verbose //[rpass3] compile-flags: -C debuginfo=2 --verbose
//[rpass4] compile-flags: -C debuginfo=2 --verbose --remap-path-prefix=/home/bors/rust=src
pub fn main() { pub fn main() {
// empty // empty

View file

@ -1,7 +1,7 @@
-include ../tools.mk -include ../tools.mk
# rust-lang/rust#70924: Test that if we add rust-src component in between two # 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 # This test uses `ln -s` rather than copying to save testing time, but its
# usage doesn't work on windows. So ignore windows. # usage doesn't work on windows. So ignore windows.