From: Jonas Schievink Date: Tue, 23 Aug 2016 20:02:47 +0000 (+0200) Subject: Make metadata encoding deterministic X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=2eeca3ccd254b49aef83f12a1cb4179a686e8551;p=rust.git 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 --- diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 9a668b69b2e..f99bdf3b890 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -862,8 +862,13 @@ fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, xrefs: FnvHashMap, u32>) { let mut xref_positions = vec![0; xrefs.len()]; + + // Encode XRefs sorted by their ID + let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); + sorted_xrefs.sort_by_key(|&(_, id)| id); + rbml_w.start_tag(tag_xref_data); - for (xref, id) in xrefs.into_iter() { + for (xref, id) in sorted_xrefs.into_iter() { xref_positions[id as usize] = rbml_w.mark_stable_position() as u32; match xref { XRef::Predicate(p) => { diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make/reproducible-build/Makefile index 8e799ca1a43..8b22dd021a9 100644 --- a/src/test/run-make/reproducible-build/Makefile +++ b/src/test/run-make/reproducible-build/Makefile @@ -1,20 +1,24 @@ -include ../tools.mk all: $(RUSTC) reproducible-build-aux.rs + mv libreproducible_build_aux.rlib first.rlib + $(RUSTC) reproducible-build-aux.rs + cp libreproducible_build_aux.rlib second.rlib + cmp "first.rlib" "second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" - nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm" - nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm" - cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1 + cmp "$(TMPDIR)/reproducible-build1" "$(TMPDIR)/reproducible-build2" || exit 1 + $(RUSTC) reproducible-build-aux.rs -g + mv libreproducible_build_aux.rlib first.rlib $(RUSTC) reproducible-build-aux.rs -g + cp libreproducible_build_aux.rlib second.rlib $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug" $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug" - nm "$(TMPDIR)/reproducible-build1-debug" | sort > "$(TMPDIR)/reproducible-build1-debug.nm" - nm "$(TMPDIR)/reproducible-build2-debug" | sort > "$(TMPDIR)/reproducible-build2-debug.nm" - cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1 + cmp "$(TMPDIR)/reproducible-build1-debug" "$(TMPDIR)/reproducible-build2-debug" || exit 1 + $(RUSTC) reproducible-build-aux.rs -O + mv libreproducible_build_aux.rlib first.rlib $(RUSTC) reproducible-build-aux.rs -O + cp libreproducible_build_aux.rlib second.rlib $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt" $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt" - nm "$(TMPDIR)/reproducible-build1-opt" | sort > "$(TMPDIR)/reproducible-build1-opt.nm" - nm "$(TMPDIR)/reproducible-build2-opt" | sort > "$(TMPDIR)/reproducible-build2-opt.nm" - cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1 + cmp "$(TMPDIR)/reproducible-build1-opt" "$(TMPDIR)/reproducible-build2-opt" || exit 1 diff --git a/src/test/run-make/reproducible-build/reproducible-build-aux.rs b/src/test/run-make/reproducible-build/reproducible-build-aux.rs index 9ef853e7996..73a62eee265 100644 --- a/src/test/run-make/reproducible-build/reproducible-build-aux.rs +++ b/src/test/run-make/reproducible-build/reproducible-build-aux.rs @@ -33,6 +33,12 @@ pub enum Enum { pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); -pub trait Trait { +pub trait Marker {} +impl Marker for char {} +impl Marker for (T, U) {} + +pub trait Trait where T1: 'static { + type Assoc: Marker; + fn foo(&self); } diff --git a/src/test/run-make/reproducible-build/reproducible-build.rs b/src/test/run-make/reproducible-build/reproducible-build.rs index dc7c702e5cc..a732cc11d60 100644 --- a/src/test/run-make/reproducible-build/reproducible-build.rs +++ b/src/test/run-make/reproducible-build/reproducible-build.rs @@ -67,7 +67,9 @@ impl Trait for u64 { fn foo(&self) {} } -impl reproducible_build_aux::Trait for TupleStruct { +impl reproducible_build_aux::Trait for TupleStruct { + type Assoc = (u8, i16); + fn foo(&self) {} } @@ -117,12 +119,10 @@ fn with_fn_once_adapter(f: F) { let _ = reproducible_build_aux::Enum::Variant3 { x: 0 }; let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4); - let object_shim: &reproducible_build_aux::Trait = &TupleStruct(0, 1, 2, 3); + let object_shim: &reproducible_build_aux::Trait = &TupleStruct(0, 1, 2, 3); object_shim.foo(); let pointer_shim: &Fn(i32) = ®ular_fn; TupleStruct(1, 2, 3, 4).bar(); } - -