Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ use std::sync::{Arc, Mutex};

use rustc_attr_ir::{AttributeKind, EncodeCrossCrate, find_attr};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut};
use rustc_data_structures::owned_slice::slice_owned;
use rustc_data_structures::stable_hash::{StableHash, StableHasher};
use rustc_data_structures::sync::{par_for_each_in, par_join};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_data_structures::thousands::usize_with_underscores;
use rustc_hir as hir;
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
use rustc_hir::definitions::DefPathData;
use rustc_hir_pretty::id_to_string;
use rustc_index::IndexVec;
Expand Down Expand Up @@ -425,6 +425,18 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {

index.encode(self);
}

fn encode_def_id_map<V: Encodable<Self>>(&mut self, map: &FxHashMap<DefId, V>) {
#[allow(rustc::potential_query_instability)]
let mut entries: Vec<(DefId, &V)> = map.iter().map(|(&k, v)| (k, v)).collect();
entries.sort_unstable_by_key(|&(def_id, _)| self.tcx.def_path_hash(def_id));

self.emit_usize(entries.len());
for (def_id, value) in entries {
def_id.encode(self);
value.encode(self);
}
}
}

// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy($value))`, which would
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,11 @@ impl<'tcx> TyEncoder<'tcx> for CacheEncoder<'tcx> {

index.encode(self);
}

#[inline]
fn encode_def_id_map<V: Encodable<Self>>(&mut self, map: &FxHashMap<DefId, V>) {
map.encode(self);
}
}

macro_rules! encoder_methods {
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/ty/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::marker::DiscriminantKind;

use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::{Decodable, Encodable};
use rustc_span::def_id::DefId;
use rustc_span::{SpanDecoder, SpanEncoder};

pub use self::ref_decodable::RefDecodable;
Expand All @@ -37,6 +38,10 @@ pub trait TyEncoder<'tcx>: SpanEncoder {
fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;

fn encode_alloc_id(&mut self, alloc_id: &AllocId);

fn encode_def_id_map<V: Encodable<Self>>(&mut self, map: &FxHashMap<DefId, V>)
where
Self: Sized;
}

pub trait TyDecoder<'tcx>:
Expand Down
40 changes: 38 additions & 2 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use std::ops::ControlFlow;
use std::ops::{ControlFlow, Deref, DerefMut};

use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_macros::{StableHash, TyDecodable, TyEncodable};
use rustc_serialize::{Decodable, Encodable};
use rustc_span::{Span, Symbol, bug, kw};
use rustc_type_ir::{TypeSuperVisitable as _, TypeVisitable, TypeVisitor};
use tracing::instrument;

use super::{Clause, InstantiatedClauses, ParamConst, ParamTy, Ty, TyCtxt, Unnormalized};
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::{self, ClauseKind, EarlyBinder, GenericArgsRef, Region, RegionKind, TyKind};

#[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash)]
Expand Down Expand Up @@ -124,7 +126,7 @@ pub struct Generics {

/// Reverse map to the `index` field of each `GenericParamDef`.
#[stable_hash(ignore)]
pub param_def_id_to_index: FxHashMap<DefId, u32>,
pub param_def_id_to_index: ParamDefIdToIndex,

@aerooneqq aerooneqq Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we apply deterministic sorting for all hash maps during metadata encoding (or as a start to all hash maps with keys DefId or LocalDefId)? This solution will fix the issue, however it is not scalable as if other developer will add FxHashMap with DefId key it will be encoded non-determinisitcally.

If there is no good solution except specializations lets use it, maybe we can implement Encodable only for HashMaps with key that implements for example StableHashForMetadata (maybe there is exising trait like StableHash that can be reused) trait and in this case we can apply deterministic encoding for all hashmaps/hashsets.

cc @petrochenkov

View changes since the review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open to any changes

I tried to make it automatic and hit coherence. The blanket Encodable for HashMap impl in
rustc_serialize always wins, so I tried out some other things like specialization, default fn on the blanket impl + impls for FxHashMap<DefId, _> and FxHashMap<LocalDefId, _> on EncodeContext, but I saw the feedback on #163321 and stopped, I do think the trait would work alot better in the long run


pub has_self: bool,
pub has_late_bound_regions: Option<Span>,
Expand Down Expand Up @@ -621,3 +623,37 @@ impl<'tcx> ConstConditions<'tcx> {
);
}
}

#[derive(Clone, Default)]
pub struct ParamDefIdToIndex(FxHashMap<DefId, u32>);

impl Deref for ParamDefIdToIndex {
type Target = FxHashMap<DefId, u32>;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for ParamDefIdToIndex {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl FromIterator<(DefId, u32)> for ParamDefIdToIndex {
fn from_iter<I: IntoIterator<Item = (DefId, u32)>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}

impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ParamDefIdToIndex {
fn encode(&self, e: &mut E) {
e.encode_def_id_map(&self.0);
}
}

impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ParamDefIdToIndex {
fn decode(d: &mut D) -> Self {
Self(Decodable::decode(d))
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_monomorphize/src/offload/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ impl<'a, 'tcx> TyEncoder<'tcx> for OffloadManifestEncoder<'a, 'tcx> {
fn encode_alloc_id(&mut self, _alloc_id: &rustc_middle::mir::interpret::AllocId) {
// AllocIds are not expected in the manifest.
}

fn encode_def_id_map<V: Encodable<Self>>(&mut self, map: &FxHashMap<DefId, V>) {
map.encode(self);
}
}

const UNRESOLVED_DEF_ID: DefId = DefId {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pub struct A {}

impl A {
pub fn f1(&self, _b1: &()) -> impl Iterator<Item = ()> + '_ {
std::iter::empty()
}
pub fn f2(&self, _b2: &()) -> impl Iterator<Item = ()> + '_ {
std::iter::empty()
}
}
11 changes: 11 additions & 0 deletions tests/run-make/parallel-reproducible-build/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ fn main() {
const TESTS: &[(&str, &[&str])] = &[
("static-muts-issue-140413", &["-Zthreads=50"]),
("derives-issue-129094", &["-Zthreads=16", "-Copt-level=3"]),
(
"generics-of-issue-163878",
&[
"-Zthreads=30",
"--crate-type=lib",
"--crate-name=test",
"-Ccodegen-units=1",
"-Zremap-cwd-prefix=reproducible_dir",
"--edition=2024",
],
),
];

for (file, args) in TESTS {
Expand Down
Loading