Skip to content

Commit 51f79b6

Browse files
committed
Auto merge of rust-lang#76233 - cuviper:unhasher, r=Mark-Simulacrum
Avoid rehashing Fingerprint as a map key This introduces a no-op `Unhasher` for map keys that are already hash- like, for example `Fingerprint` and its wrapper `DefPathHash`. For these we can directly produce the `u64` hash for maps. The first use of this is `def_path_hash_to_def_id: Option<UnhashMap<DefPathHash, DefId>>`. cc rust-lang#56308 r? @eddyb
2 parents 80fc9b0 + 469ca37 commit 51f79b6

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

compiler/rustc_data_structures/src/fingerprint.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use rustc_serialize::{
33
opaque::{self, EncodeResult},
44
Decodable, Encodable,
55
};
6+
use std::hash::{Hash, Hasher};
67
use std::mem;
78

8-
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
9+
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
910
pub struct Fingerprint(u64, u64);
1011

1112
impl Fingerprint {
@@ -76,6 +77,33 @@ impl ::std::fmt::Display for Fingerprint {
7677
}
7778
}
7879

80+
impl Hash for Fingerprint {
81+
#[inline]
82+
fn hash<H: Hasher>(&self, state: &mut H) {
83+
state.write_fingerprint(self);
84+
}
85+
}
86+
87+
trait FingerprintHasher {
88+
fn write_fingerprint(&mut self, fingerprint: &Fingerprint);
89+
}
90+
91+
impl<H: Hasher> FingerprintHasher for H {
92+
#[inline]
93+
default fn write_fingerprint(&mut self, fingerprint: &Fingerprint) {
94+
self.write_u64(fingerprint.0);
95+
self.write_u64(fingerprint.1);
96+
}
97+
}
98+
99+
impl FingerprintHasher for crate::unhash::Unhasher {
100+
#[inline]
101+
fn write_fingerprint(&mut self, fingerprint: &Fingerprint) {
102+
// `Unhasher` only wants a single `u64`
103+
self.write_u64(fingerprint.0);
104+
}
105+
}
106+
79107
impl stable_hasher::StableHasherResult for Fingerprint {
80108
#[inline]
81109
fn finish(hasher: stable_hasher::StableHasher) -> Self {

compiler/rustc_data_structures/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ pub use atomic_ref::AtomicRef;
103103
pub mod frozen;
104104
pub mod tagged_ptr;
105105
pub mod temp_dir;
106+
pub mod unhash;
106107

107108
pub struct OnDrop<F: Fn()>(pub F);
108109

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use std::collections::{HashMap, HashSet};
2+
use std::hash::{BuildHasherDefault, Hasher};
3+
4+
pub type UnhashMap<K, V> = HashMap<K, V, BuildHasherDefault<Unhasher>>;
5+
pub type UnhashSet<V> = HashSet<V, BuildHasherDefault<Unhasher>>;
6+
7+
/// This no-op hasher expects only a single `write_u64` call. It's intended for
8+
/// map keys that already have hash-like quality, like `Fingerprint`.
9+
#[derive(Default)]
10+
pub struct Unhasher {
11+
value: u64,
12+
}
13+
14+
impl Hasher for Unhasher {
15+
#[inline]
16+
fn finish(&self) -> u64 {
17+
self.value
18+
}
19+
20+
fn write(&mut self, _bytes: &[u8]) {
21+
unimplemented!("use write_u64");
22+
}
23+
24+
#[inline]
25+
fn write_u64(&mut self, value: u64) {
26+
debug_assert_eq!(0, self.value, "Unhasher doesn't mix values!");
27+
self.value = value;
28+
}
29+
}

compiler/rustc_middle/src/ty/context.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use rustc_data_structures::stable_hasher::{
3434
hash_stable_hashmap, HashStable, StableHasher, StableVec,
3535
};
3636
use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
37+
use rustc_data_structures::unhash::UnhashMap;
3738
use rustc_errors::ErrorReported;
3839
use rustc_hir as hir;
3940
use rustc_hir::def::{DefKind, Res};
@@ -935,7 +936,7 @@ pub struct GlobalCtxt<'tcx> {
935936

936937
/// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate
937938
/// as well as all upstream crates. Only populated in incremental mode.
938-
pub def_path_hash_to_def_id: Option<FxHashMap<DefPathHash, DefId>>,
939+
pub def_path_hash_to_def_id: Option<UnhashMap<DefPathHash, DefId>>,
939940

940941
pub queries: query::Queries<'tcx>,
941942

@@ -1104,7 +1105,7 @@ impl<'tcx> TyCtxt<'tcx> {
11041105
let def_path_hash_to_def_id = if s.opts.build_dep_graph() {
11051106
let capacity = definitions.def_path_table().num_def_ids()
11061107
+ crates.iter().map(|cnum| cstore.num_def_ids(*cnum)).sum::<usize>();
1107-
let mut map = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
1108+
let mut map = UnhashMap::with_capacity_and_hasher(capacity, Default::default());
11081109

11091110
map.extend(definitions.def_path_table().all_def_path_hashes_and_def_ids(LOCAL_CRATE));
11101111
for cnum in &crates {

0 commit comments

Comments
 (0)