Skip to content

Commit 2eeca3c

Browse files
Make metadata encoding deterministic
`ty::Predicate` was being used as a key for a hash map, but its hash implementation indirectly hashed addresses, which vary between each compiler run. This is fixed by sorting predicates by their ID before encoding them. In my tests, rustc is now able to produce deterministic results when compiling libcore and libstd. I've beefed up `run-make/reproducible-build` to compare the produced artifacts bit-by-bit. This doesn't catch everything, but should be a good start. cc #34902
1 parent 5adf003 commit 2eeca3c

File tree

4 files changed

+30
-15
lines changed

4 files changed

+30
-15
lines changed

src/librustc_metadata/encoder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,8 +862,13 @@ fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
862862
xrefs: FnvHashMap<XRef<'tcx>, u32>)
863863
{
864864
let mut xref_positions = vec![0; xrefs.len()];
865+
866+
// Encode XRefs sorted by their ID
867+
let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect();
868+
sorted_xrefs.sort_by_key(|&(_, id)| id);
869+
865870
rbml_w.start_tag(tag_xref_data);
866-
for (xref, id) in xrefs.into_iter() {
871+
for (xref, id) in sorted_xrefs.into_iter() {
867872
xref_positions[id as usize] = rbml_w.mark_stable_position() as u32;
868873
match xref {
869874
XRef::Predicate(p) => {
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
-include ../tools.mk
22
all:
33
$(RUSTC) reproducible-build-aux.rs
4+
mv libreproducible_build_aux.rlib first.rlib
5+
$(RUSTC) reproducible-build-aux.rs
6+
cp libreproducible_build_aux.rlib second.rlib
7+
cmp "first.rlib" "second.rlib" || exit 1
48
$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1"
59
$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2"
6-
nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm"
7-
nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm"
8-
cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1
10+
cmp "$(TMPDIR)/reproducible-build1" "$(TMPDIR)/reproducible-build2" || exit 1
11+
$(RUSTC) reproducible-build-aux.rs -g
12+
mv libreproducible_build_aux.rlib first.rlib
913
$(RUSTC) reproducible-build-aux.rs -g
14+
cp libreproducible_build_aux.rlib second.rlib
1015
$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug"
1116
$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug"
12-
nm "$(TMPDIR)/reproducible-build1-debug" | sort > "$(TMPDIR)/reproducible-build1-debug.nm"
13-
nm "$(TMPDIR)/reproducible-build2-debug" | sort > "$(TMPDIR)/reproducible-build2-debug.nm"
14-
cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1
17+
cmp "$(TMPDIR)/reproducible-build1-debug" "$(TMPDIR)/reproducible-build2-debug" || exit 1
18+
$(RUSTC) reproducible-build-aux.rs -O
19+
mv libreproducible_build_aux.rlib first.rlib
1520
$(RUSTC) reproducible-build-aux.rs -O
21+
cp libreproducible_build_aux.rlib second.rlib
1622
$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt"
1723
$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt"
18-
nm "$(TMPDIR)/reproducible-build1-opt" | sort > "$(TMPDIR)/reproducible-build1-opt.nm"
19-
nm "$(TMPDIR)/reproducible-build2-opt" | sort > "$(TMPDIR)/reproducible-build2-opt.nm"
20-
cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1
24+
cmp "$(TMPDIR)/reproducible-build1-opt" "$(TMPDIR)/reproducible-build2-opt" || exit 1

src/test/run-make/reproducible-build/reproducible-build-aux.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ pub enum Enum {
3333

3434
pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64);
3535

36-
pub trait Trait<T1, T2> {
36+
pub trait Marker {}
37+
impl Marker for char {}
38+
impl<T, U> Marker for (T, U) {}
39+
40+
pub trait Trait<T1: Marker + Marker + Marker, T2> where T1: 'static {
41+
type Assoc: Marker;
42+
3743
fn foo(&self);
3844
}

src/test/run-make/reproducible-build/reproducible-build.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ impl Trait<i32, u64> for u64 {
6767
fn foo(&self) {}
6868
}
6969

70-
impl reproducible_build_aux::Trait<char, String> for TupleStruct {
70+
impl<T: reproducible_build_aux::Marker + 'static> reproducible_build_aux::Trait<T, String> for TupleStruct {
71+
type Assoc = (u8, i16);
72+
7173
fn foo(&self) {}
7274
}
7375

@@ -117,12 +119,10 @@ fn main() {
117119
let _ = reproducible_build_aux::Enum::Variant3 { x: 0 };
118120
let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4);
119121

120-
let object_shim: &reproducible_build_aux::Trait<char, String> = &TupleStruct(0, 1, 2, 3);
122+
let object_shim: &reproducible_build_aux::Trait<char, String, Assoc=(u8, i16)> = &TupleStruct(0, 1, 2, 3);
121123
object_shim.foo();
122124

123125
let pointer_shim: &Fn(i32) = &regular_fn;
124126

125127
TupleStruct(1, 2, 3, 4).bar();
126128
}
127-
128-

0 commit comments

Comments
 (0)