Skip to content

Commit b8be316

Browse files
committed
Auto merge of rust-lang#86045 - jsgf:fix-emit-path-hashing, r=bjorn3
Fix emit path hashing With `--emit KIND=PATH`, the PATH should not affect hashes used for dependency tracking. It does not with other ways of specifying output paths (`-o` or `--out-dir`). Also updates `rustc -Zls` to print more info about crates, which is used here to implement a `run-make` test. It seems there was already a test explicitly checking that `OutputTypes` hash *is* affected by the path. I think this behaviour is wrong, so I updated the test.
2 parents 80926fc + 4514697 commit b8be316

File tree

6 files changed

+151
-33
lines changed

6 files changed

+151
-33
lines changed

compiler/rustc_interface/src/tests.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ fn assert_different_hash(x: &Options, y: &Options) {
9696
assert_same_clone(y);
9797
}
9898

99+
fn assert_non_crate_hash_different(x: &Options, y: &Options) {
100+
assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
101+
assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
102+
// Check clone
103+
assert_same_clone(x);
104+
assert_same_clone(y);
105+
}
106+
99107
// When the user supplies --test we should implicitly supply --cfg test
100108
#[test]
101109
fn test_switch_implies_cfg_test() {
@@ -152,9 +160,9 @@ fn test_output_types_tracking_hash_different_paths() {
152160
v2.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]);
153161
v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
154162

155-
assert_different_hash(&v1, &v2);
156-
assert_different_hash(&v1, &v3);
157-
assert_different_hash(&v2, &v3);
163+
assert_non_crate_hash_different(&v1, &v2);
164+
assert_non_crate_hash_different(&v1, &v3);
165+
assert_non_crate_hash_different(&v2, &v3);
158166
}
159167

160168
#[test]
@@ -712,7 +720,6 @@ fn test_debugging_options_tracking_hash() {
712720
tracked!(mir_opt_level, Some(4));
713721
tracked!(mutable_noalias, Some(true));
714722
tracked!(new_llvm_pass_manager, Some(true));
715-
tracked!(no_codegen, true);
716723
tracked!(no_generate_arange_section, true);
717724
tracked!(no_link, true);
718725
tracked!(osx_rpath_install_name, true);
@@ -747,6 +754,16 @@ fn test_debugging_options_tracking_hash() {
747754
tracked!(use_ctors_section, Some(true));
748755
tracked!(verify_llvm_ir, true);
749756
tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
757+
758+
macro_rules! tracked_no_crate_hash {
759+
($name: ident, $non_default_value: expr) => {
760+
opts = reference.clone();
761+
assert_ne!(opts.debugging_opts.$name, $non_default_value);
762+
opts.debugging_opts.$name = $non_default_value;
763+
assert_non_crate_hash_different(&reference, &opts);
764+
};
765+
}
766+
tracked_no_crate_hash!(no_codegen, true);
750767
}
751768

752769
#[test]

compiler/rustc_metadata/src/rmeta/decoder.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -601,10 +601,23 @@ impl MetadataBlob {
601601
}
602602

603603
crate fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> {
604-
write!(out, "=External Dependencies=\n")?;
605604
let root = self.get_root();
605+
writeln!(out, "Crate info:")?;
606+
writeln!(out, "name {}{}", root.name, root.extra_filename)?;
607+
writeln!(out, "hash {} stable_crate_id {:?}", root.hash, root.stable_crate_id)?;
608+
writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
609+
writeln!(out, "=External Dependencies=")?;
606610
for (i, dep) in root.crate_deps.decode(self).enumerate() {
607-
write!(out, "{} {}{}\n", i + 1, dep.name, dep.extra_filename)?;
611+
writeln!(
612+
out,
613+
"{} {}{} hash {} host_hash {:?} kind {:?}",
614+
i + 1,
615+
dep.name,
616+
dep.extra_filename,
617+
dep.hash,
618+
dep.host_hash,
619+
dep.kind
620+
)?;
608621
}
609622
write!(out, "\n")?;
610623
Ok(())

compiler/rustc_session/src/config.rs

+64-21
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::collections::btree_map::{
3131
};
3232
use std::collections::{BTreeMap, BTreeSet};
3333
use std::fmt;
34+
use std::hash::Hash;
3435
use std::iter::{self, FromIterator};
3536
use std::path::{Path, PathBuf};
3637
use std::str::{self, FromStr};
@@ -325,12 +326,11 @@ impl Default for TrimmedDefPaths {
325326

326327
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
327328
/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
328-
/// dependency tracking for command-line arguments.
329-
#[derive(Clone, Hash, Debug)]
329+
/// dependency tracking for command-line arguments. Also only hash keys, since tracking
330+
/// should only depend on the output types, not the paths they're written to.
331+
#[derive(Clone, Debug, Hash)]
330332
pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
331333

332-
impl_stable_hash_via_hash!(OutputTypes);
333-
334334
impl OutputTypes {
335335
pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
336336
OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone()))))
@@ -2426,8 +2426,8 @@ crate mod dep_tracking {
24262426
use super::LdImpl;
24272427
use super::{
24282428
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
2429-
LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
2430-
SymbolManglingVersion, TrimmedDefPaths,
2429+
LtoCli, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm,
2430+
SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
24312431
};
24322432
use crate::lint;
24332433
use crate::options::WasiExecModel;
@@ -2443,25 +2443,35 @@ crate mod dep_tracking {
24432443
use std::path::PathBuf;
24442444

24452445
pub trait DepTrackingHash {
2446-
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
2446+
fn hash(
2447+
&self,
2448+
hasher: &mut DefaultHasher,
2449+
error_format: ErrorOutputType,
2450+
for_crate_hash: bool,
2451+
);
24472452
}
24482453

24492454
macro_rules! impl_dep_tracking_hash_via_hash {
24502455
($($t:ty),+ $(,)?) => {$(
24512456
impl DepTrackingHash for $t {
2452-
fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
2457+
fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType, _for_crate_hash: bool) {
24532458
Hash::hash(self, hasher);
24542459
}
24552460
}
24562461
)+};
24572462
}
24582463

24592464
impl<T: DepTrackingHash> DepTrackingHash for Option<T> {
2460-
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2465+
fn hash(
2466+
&self,
2467+
hasher: &mut DefaultHasher,
2468+
error_format: ErrorOutputType,
2469+
for_crate_hash: bool,
2470+
) {
24612471
match self {
24622472
Some(x) => {
24632473
Hash::hash(&1, hasher);
2464-
DepTrackingHash::hash(x, hasher, error_format);
2474+
DepTrackingHash::hash(x, hasher, error_format, for_crate_hash);
24652475
}
24662476
None => Hash::hash(&0, hasher),
24672477
}
@@ -2491,7 +2501,6 @@ crate mod dep_tracking {
24912501
LtoCli,
24922502
DebugInfo,
24932503
UnstableFeatures,
2494-
OutputTypes,
24952504
NativeLib,
24962505
NativeLibKind,
24972506
SanitizerSet,
@@ -2505,18 +2514,24 @@ crate mod dep_tracking {
25052514
SourceFileHashAlgorithm,
25062515
TrimmedDefPaths,
25072516
Option<LdImpl>,
2517+
OutputType,
25082518
);
25092519

25102520
impl<T1, T2> DepTrackingHash for (T1, T2)
25112521
where
25122522
T1: DepTrackingHash,
25132523
T2: DepTrackingHash,
25142524
{
2515-
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2525+
fn hash(
2526+
&self,
2527+
hasher: &mut DefaultHasher,
2528+
error_format: ErrorOutputType,
2529+
for_crate_hash: bool,
2530+
) {
25162531
Hash::hash(&0, hasher);
2517-
DepTrackingHash::hash(&self.0, hasher, error_format);
2532+
DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
25182533
Hash::hash(&1, hasher);
2519-
DepTrackingHash::hash(&self.1, hasher, error_format);
2534+
DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
25202535
}
25212536
}
25222537

@@ -2526,22 +2541,49 @@ crate mod dep_tracking {
25262541
T2: DepTrackingHash,
25272542
T3: DepTrackingHash,
25282543
{
2529-
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2544+
fn hash(
2545+
&self,
2546+
hasher: &mut DefaultHasher,
2547+
error_format: ErrorOutputType,
2548+
for_crate_hash: bool,
2549+
) {
25302550
Hash::hash(&0, hasher);
2531-
DepTrackingHash::hash(&self.0, hasher, error_format);
2551+
DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
25322552
Hash::hash(&1, hasher);
2533-
DepTrackingHash::hash(&self.1, hasher, error_format);
2553+
DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
25342554
Hash::hash(&2, hasher);
2535-
DepTrackingHash::hash(&self.2, hasher, error_format);
2555+
DepTrackingHash::hash(&self.2, hasher, error_format, for_crate_hash);
25362556
}
25372557
}
25382558

25392559
impl<T: DepTrackingHash> DepTrackingHash for Vec<T> {
2540-
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2560+
fn hash(
2561+
&self,
2562+
hasher: &mut DefaultHasher,
2563+
error_format: ErrorOutputType,
2564+
for_crate_hash: bool,
2565+
) {
25412566
Hash::hash(&self.len(), hasher);
25422567
for (index, elem) in self.iter().enumerate() {
25432568
Hash::hash(&index, hasher);
2544-
DepTrackingHash::hash(elem, hasher, error_format);
2569+
DepTrackingHash::hash(elem, hasher, error_format, for_crate_hash);
2570+
}
2571+
}
2572+
}
2573+
2574+
impl DepTrackingHash for OutputTypes {
2575+
fn hash(
2576+
&self,
2577+
hasher: &mut DefaultHasher,
2578+
error_format: ErrorOutputType,
2579+
for_crate_hash: bool,
2580+
) {
2581+
Hash::hash(&self.0.len(), hasher);
2582+
for (key, val) in &self.0 {
2583+
DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
2584+
if !for_crate_hash {
2585+
DepTrackingHash::hash(val, hasher, error_format, for_crate_hash);
2586+
}
25452587
}
25462588
}
25472589
}
@@ -2551,13 +2593,14 @@ crate mod dep_tracking {
25512593
sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
25522594
hasher: &mut DefaultHasher,
25532595
error_format: ErrorOutputType,
2596+
for_crate_hash: bool,
25542597
) {
25552598
for (key, sub_hash) in sub_hashes {
25562599
// Using Hash::hash() instead of DepTrackingHash::hash() is fine for
25572600
// the keys, as they are just plain strings
25582601
Hash::hash(&key.len(), hasher);
25592602
Hash::hash(key, hasher);
2560-
sub_hash.hash(hasher, error_format);
2603+
sub_hash.hash(hasher, error_format, for_crate_hash);
25612604
}
25622605
}
25632606
}

compiler/rustc_session/src/options.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ macro_rules! hash_substruct {
4848
($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED_NO_CRATE_HASH]) => {{}};
4949
($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [SUBSTRUCT]) => {
5050
use crate::config::dep_tracking::DepTrackingHash;
51-
$opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash($hasher, $error_format);
51+
$opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash(
52+
$hasher,
53+
$error_format,
54+
$for_crate_hash,
55+
);
5256
};
5357
}
5458

@@ -79,7 +83,8 @@ macro_rules! top_level_options {
7983
let mut hasher = DefaultHasher::new();
8084
dep_tracking::stable_hash(sub_hashes,
8185
&mut hasher,
82-
self.error_format);
86+
self.error_format,
87+
for_crate_hash);
8388
$({
8489
hash_substruct!($opt,
8590
&self.$opt,
@@ -236,19 +241,21 @@ macro_rules! options {
236241
build_options(matches, $stat, $prefix, $outputname, error_format)
237242
}
238243

239-
fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
244+
fn dep_tracking_hash(&self, for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
240245
let mut sub_hashes = BTreeMap::new();
241246
$({
242247
hash_opt!($opt,
243248
&self.$opt,
244249
&mut sub_hashes,
245-
_for_crate_hash,
250+
for_crate_hash,
246251
[$dep_tracking_marker]);
247252
})*
248253
let mut hasher = DefaultHasher::new();
249254
dep_tracking::stable_hash(sub_hashes,
250255
&mut hasher,
251-
error_format);
256+
error_format,
257+
for_crate_hash
258+
);
252259
hasher.finish()
253260
}
254261
}
@@ -1148,7 +1155,7 @@ options! {
11481155
"the directory the NLL facts are dumped into (default: `nll-facts`)"),
11491156
no_analysis: bool = (false, parse_no_flag, [UNTRACKED],
11501157
"parse and expand the source, but run no analysis"),
1151-
no_codegen: bool = (false, parse_no_flag, [TRACKED],
1158+
no_codegen: bool = (false, parse_no_flag, [TRACKED_NO_CRATE_HASH],
11521159
"run all passes except codegen; no output"),
11531160
no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED],
11541161
"omit DWARF address ranges that give faster lookups"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
-include ../../run-make-fulldeps/tools.mk
2+
3+
OUT=$(TMPDIR)/emit
4+
5+
# --emit KIND=PATH should not affect crate hash vs --emit KIND
6+
all: $(OUT)/a/libfoo.rlib $(OUT)/b/libfoo.rlib $(OUT)/c/libfoo.rlib \
7+
$(TMPDIR)/libfoo.rlib
8+
$(RUSTC) -Zls $(TMPDIR)/libfoo.rlib > $(TMPDIR)/base.txt
9+
$(RUSTC) -Zls $(OUT)/a/libfoo.rlib > $(TMPDIR)/a.txt
10+
$(RUSTC) -Zls $(OUT)/b/libfoo.rlib > $(TMPDIR)/b.txt
11+
$(RUSTC) -Zls $(OUT)/c/libfoo.rlib > $(TMPDIR)/c.txt
12+
13+
diff $(TMPDIR)/base.txt $(TMPDIR)/a.txt
14+
diff $(TMPDIR)/base.txt $(TMPDIR)/b.txt
15+
16+
# Different KIND parameters do affect hash.
17+
# diff exits 1 on difference, 2 on trouble
18+
diff $(TMPDIR)/base.txt $(TMPDIR)/c.txt ; test "$$?" -eq 1
19+
20+
# Default output name
21+
$(TMPDIR)/libfoo.rlib: foo.rs
22+
$(RUSTC) --emit link foo.rs
23+
24+
# Output named with -o
25+
$(OUT)/a/libfoo.rlib: foo.rs
26+
mkdir -p $(OUT)/a
27+
$(RUSTC) --emit link -o $@ foo.rs
28+
29+
# Output named with KIND=PATH
30+
$(OUT)/b/libfoo.rlib: foo.rs
31+
mkdir -p $(OUT)/b
32+
$(RUSTC) --emit link=$@ foo.rs
33+
34+
# Output multiple kinds
35+
$(OUT)/c/libfoo.rlib: foo.rs
36+
mkdir -p $(OUT)/c
37+
$(RUSTC) --emit link=$@,metadata foo.rs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#![crate_type = "rlib"]

0 commit comments

Comments
 (0)