Skip to content

Commit ecec737

Browse files
krallinfacebook-github-bot
authored andcommitted
StrongHash: allow passing in a regular Hasher
Summary: StrongHash mixes two different concerns: - Arbitrary output size (StrongHasher). - Not using precomputed weak hashes (StrongHash). However, you can want the regular hash output size (aka 64 bits) while not wanting to use precomputed weak hashes, but right now that's not allowed. This is typically useful if you are passing your thing to a library that wants a regular 64 bit hash. This diff fixes that by allowing you to pass a regular `Hasher` into `fn strong_hash`, and also updates the docs to express the notion that it is OK to want to use StrongHash even if your hasher isn't a StrongHasher. Note: ideally you wouldn't want to let someone use a `StrongHasher` and then pass it into `hash` instead of `strong_hash`, but that was already possible before, and it doesn't seem like it's been a problem. Reviewed By: cjhopman Differential Revision: D73095294 fbshipit-source-id: 80e14308c8547f82b84e25fd20c573f5a98e8cd6
1 parent 3f7fd58 commit ecec737

File tree

3 files changed

+29
-27
lines changed

3 files changed

+29
-27
lines changed

gazebo/strong_hash/src/lib.rs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ use std::sync::Arc;
1515

1616
pub use strong_hash_derive::StrongHash;
1717

18-
/// `StrongHasher`` is a trait for hashing any type that implements the `StrongHash`
19-
/// trait. It is similar to `std::hash::Hasher`. The key difference is that `StrongHasher`
20-
/// produces a vec of bytes as the hash.
18+
/// `StrongHasher` is a trait for hashing functions that return more than 64
19+
/// bits of output. The key difference between `std::hash::Hasher` and
20+
/// `StrongHasher` is that `StrongHasher` produces a vec of bytes as the hash.
2121
///
2222
/// For example, a `DefaultHasher` implementation of `StrongHasher` is as follows.
2323
///
@@ -42,13 +42,16 @@ impl<H: StrongHasher + ?Sized> StrongHasher for &mut H {
4242
StrongHasher::finish(*self)
4343
}
4444
}
45-
/// `StrongHash`` is a trait for hashing any type that can be hashed. It is similar
46-
/// to `std::hash::Hash`` except that the hash produced is stored in as a vec of bytes
47-
/// in `Vec<u8>`` that can accommodate hashing schemes of different lengths.
48-
/// `StrongHash` is intended to be used with cryptographic hashing algorithms like blake3.
45+
46+
/// `StrongHash`` is a trait that is notionally similar to `std::hash::Hash`,
47+
/// but carries the implicit expectation that the hash that will be produced
48+
/// should be as perturbed as possible.
49+
///
4950
/// When implementing `StrongHash` for an object, you should always hash the entire object
5051
/// and not a subset or a lossy representation of the object unless you are hashing another
51-
/// cryptographic hash of the object.
52+
/// cryptographic hash of the object. If you do the latter, a good rule of thumb
53+
/// is that you should feel comfortable also using that same hash for equality
54+
/// checks.
5255
///
5356
/// By default, `StrongHash` is implemented for most rust types that implement
5457
/// `std::hash::Hash`. including all primitive types, strings, and vectors.
@@ -84,14 +87,14 @@ impl<H: StrongHasher + ?Sized> StrongHasher for &mut H {
8487
/// }
8588
/// ```
8689
pub trait StrongHash {
87-
fn strong_hash<H: StrongHasher>(&self, state: &mut H);
90+
fn strong_hash<H: Hasher>(&self, state: &mut H);
8891
}
8992

9093
macro_rules! impl_strong_hash_for_impl_hash {
9194
($($t:ty)*) => {
9295
$(
9396
impl StrongHash for $t {
94-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
97+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
9598
self.hash(state);
9699
}
97100
}
@@ -102,7 +105,7 @@ macro_rules! impl_strong_hash_for_impl_hash {
102105
impl_strong_hash_for_impl_hash!(bool u8 i8 u16 i16 u32 i32 u64 i64 usize str &str String);
103106

104107
impl<T: StrongHash> StrongHash for [T] {
105-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
108+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
106109
self.len().strong_hash(state);
107110
for item in self.iter() {
108111
item.strong_hash(state);
@@ -111,20 +114,20 @@ impl<T: StrongHash> StrongHash for [T] {
111114
}
112115

113116
impl<T: StrongHash> StrongHash for &[T] {
114-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
117+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
115118
<[T] as StrongHash>::strong_hash(*self, state);
116119
}
117120
}
118121

119122
impl<T: StrongHash> StrongHash for Vec<T> {
120-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
123+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
121124
self.len().strong_hash(state);
122125
(&self[..]).strong_hash(state);
123126
}
124127
}
125128

126129
impl<T: StrongHash> StrongHash for Option<T> {
127-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
130+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
128131
self.is_some().strong_hash(state);
129132
if let Some(t) = self.as_ref() {
130133
t.strong_hash(state);
@@ -133,26 +136,26 @@ impl<T: StrongHash> StrongHash for Option<T> {
133136
}
134137

135138
impl StrongHash for () {
136-
fn strong_hash<H: StrongHasher>(&self, _state: &mut H) {}
139+
fn strong_hash<H: Hasher>(&self, _state: &mut H) {}
137140
}
138141

139142
impl<A: StrongHash> StrongHash for (A,) {
140-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
143+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
141144
1.strong_hash(state);
142145
self.0.strong_hash(state);
143146
}
144147
}
145148

146149
impl<A: StrongHash, B: StrongHash> StrongHash for (A, B) {
147-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
150+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
148151
2.strong_hash(state);
149152
self.0.strong_hash(state);
150153
self.1.strong_hash(state);
151154
}
152155
}
153156

154157
impl<A: StrongHash, B: StrongHash, C: StrongHash> StrongHash for (A, B, C) {
155-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
158+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
156159
3.strong_hash(state);
157160
self.0.strong_hash(state);
158161
self.1.strong_hash(state);
@@ -161,19 +164,19 @@ impl<A: StrongHash, B: StrongHash, C: StrongHash> StrongHash for (A, B, C) {
161164
}
162165

163166
impl<T: StrongHash + ?Sized> StrongHash for Box<T> {
164-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
167+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
165168
self.as_ref().strong_hash(state);
166169
}
167170
}
168171

169172
impl<T: StrongHash + ?Sized> StrongHash for Arc<T> {
170-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
173+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
171174
self.as_ref().strong_hash(state);
172175
}
173176
}
174177

175178
impl<K: StrongHash, V: StrongHash> StrongHash for BTreeMap<K, V> {
176-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
179+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
177180
self.len().strong_hash(state);
178181
for (k, v) in self.iter() {
179182
k.strong_hash(state);
@@ -183,7 +186,7 @@ impl<K: StrongHash, V: StrongHash> StrongHash for BTreeMap<K, V> {
183186
}
184187

185188
impl<K: StrongHash, V: StrongHash> StrongHash for HashMap<K, V> {
186-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
189+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
187190
self.len().strong_hash(state);
188191
for (k, v) in self.iter() {
189192
k.strong_hash(state);
@@ -193,7 +196,7 @@ impl<K: StrongHash, V: StrongHash> StrongHash for HashMap<K, V> {
193196
}
194197

195198
impl StrongHash for *const () {
196-
fn strong_hash<H: StrongHasher>(&self, state: &mut H) {
199+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
197200
(*self as usize).strong_hash(state);
198201
}
199202
}

gazebo/strong_hash_derive/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn derive_hash(input: TokenStream) -> TokenStream {
2626
let members = data.fields.members();
2727
quote! {
2828
impl #impl_generics strong_hash::StrongHash for #name #type_generics #where_clause {
29-
fn strong_hash<H: strong_hash::StrongHasher>(&self, state: &mut H) {
29+
fn strong_hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
3030
#(StrongHash::strong_hash(&self.#members, state));*
3131
}
3232
}
@@ -81,7 +81,7 @@ pub fn derive_hash(input: TokenStream) -> TokenStream {
8181
.collect::<Vec<_>>();
8282
quote! {
8383
impl #impl_generics strong_hash::StrongHash for #name #type_generics #where_clause {
84-
fn strong_hash<H: strong_hash::StrongHasher>(&self, state: &mut H) {
84+
fn strong_hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
8585
match self {
8686
#(#hash_impl),*
8787
}

starlark_map/src/hashed.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use allocative::Allocative;
2525
use dupe::Dupe;
2626
use equivalent::Equivalent;
2727
use strong_hash::StrongHash;
28-
use strong_hash::StrongHasher;
2928

3029
use crate::hash_value::StarlarkHashValue;
3130

@@ -46,7 +45,7 @@ impl<K> Hash for Hashed<K> {
4645
}
4746

4847
impl<K: StrongHash> StrongHash for Hashed<K> {
49-
fn strong_hash<S: StrongHasher>(&self, state: &mut S) {
48+
fn strong_hash<S: Hasher>(&self, state: &mut S) {
5049
// Only hash the key, not the (weak) hash.
5150
self.key.strong_hash(state);
5251
}

0 commit comments

Comments
 (0)