Skip to content

Commit 50e0cc5

Browse files
committed
Auto merge of rust-lang#86151 - scottmcm:simple-hash-of, r=joshtriplett
Add `BuildHasher::hash_one` as unstable Inspired by https://github.com/rust-lang/rust/pull/86140/files#diff-246941135168fbc44fce120385ee9c3156e08a1c3e2697985b56dcb8d728eedeR2416, where I wanted to write a quick test for a `Hash` implementation and it took more of a dance than I'd hoped. It looks like this would be handy in hashtable implementations, too -- a quick look at hashbrown found two places where it needs to do the same dance: https://github.com/rust-lang/hashbrown/blob/6302512a8a514fe5bd442464ebcd78139c82e1e2/src/map.rs#L247-L270 I wanted to get a "seems plausible" from a libs member before making a tracking issue, so random-sampling the intersection of highfive and governance gave me... r? `@joshtriplett` (As always, bikeshed away! And let me know if I missed something obvious again that I should have used instead.)
2 parents 50a9081 + 579d19b commit 50e0cc5

File tree

3 files changed

+50
-16
lines changed

3 files changed

+50
-16
lines changed

library/alloc/src/vec/mod.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -2411,18 +2411,13 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
24112411
/// as required by the `core::borrow::Borrow` implementation.
24122412
///
24132413
/// ```
2414-
/// use std::hash::{BuildHasher, Hash, Hasher};
2415-
///
2416-
/// fn hash_of(x: impl Hash, b: &impl BuildHasher) -> u64 {
2417-
/// let mut h = b.build_hasher();
2418-
/// x.hash(&mut h);
2419-
/// h.finish()
2420-
/// }
2414+
/// #![feature(build_hasher_simple_hash_one)]
2415+
/// use std::hash::BuildHasher;
24212416
///
24222417
/// let b = std::collections::hash_map::RandomState::new();
24232418
/// let v: Vec<u8> = vec![0xa8, 0x3c, 0x09];
24242419
/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
2425-
/// assert_eq!(hash_of(v, &b), hash_of(s, &b));
2420+
/// assert_eq!(b.hash_one(v), b.hash_one(s));
24262421
/// ```
24272422
#[stable(feature = "rust1", since = "1.0.0")]
24282423
impl<T: Hash, A: Allocator> Hash for Vec<T, A> {

library/core/src/array/mod.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,13 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
143143
/// as required by the `Borrow` implementation.
144144
///
145145
/// ```
146-
/// use std::hash::{BuildHasher, Hash, Hasher};
147-
///
148-
/// fn hash_of(x: impl Hash, b: &impl BuildHasher) -> u64 {
149-
/// let mut h = b.build_hasher();
150-
/// x.hash(&mut h);
151-
/// h.finish()
152-
/// }
146+
/// #![feature(build_hasher_simple_hash_one)]
147+
/// use std::hash::BuildHasher;
153148
///
154149
/// let b = std::collections::hash_map::RandomState::new();
155150
/// let a: [u8; 3] = [0xa8, 0x3c, 0x09];
156151
/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
157-
/// assert_eq!(hash_of(a, &b), hash_of(s, &b));
152+
/// assert_eq!(b.hash_one(a), b.hash_one(s));
158153
/// ```
159154
#[stable(feature = "rust1", since = "1.0.0")]
160155
impl<T: Hash, const N: usize> Hash for [T; N] {

library/core/src/hash/mod.rs

+44
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,50 @@ pub trait BuildHasher {
481481
/// ```
482482
#[stable(since = "1.7.0", feature = "build_hasher")]
483483
fn build_hasher(&self) -> Self::Hasher;
484+
485+
/// Calculates the hash of a single value.
486+
///
487+
/// This is intended as a convenience for code which *consumes* hashes, such
488+
/// as the implementation of a hash table or in unit tests that check
489+
/// whether a custom [`Hash`] implementation behaves as expected.
490+
///
491+
/// This must not be used in any code which *creates* hashes, such as in an
492+
/// implementation of [`Hash`]. The way to create a combined hash of
493+
/// multiple values is to call [`Hash::hash`] multiple times using the same
494+
/// [`Hasher`], not to call this method repeatedly and combine the results.
495+
///
496+
/// # Example
497+
///
498+
/// ```
499+
/// #![feature(build_hasher_simple_hash_one)]
500+
///
501+
/// use std::cmp::{max, min};
502+
/// use std::hash::{BuildHasher, Hash, Hasher};
503+
/// struct OrderAmbivalentPair<T: Ord>(T, T);
504+
/// impl<T: Ord + Hash> Hash for OrderAmbivalentPair<T> {
505+
/// fn hash<H: Hasher>(&self, hasher: &mut H) {
506+
/// min(&self.0, &self.1).hash(hasher);
507+
/// max(&self.0, &self.1).hash(hasher);
508+
/// }
509+
/// }
510+
///
511+
/// // Then later, in a `#[test]` for the type...
512+
/// let bh = std::collections::hash_map::RandomState::new();
513+
/// assert_eq!(
514+
/// bh.hash_one(OrderAmbivalentPair(1, 2)),
515+
/// bh.hash_one(OrderAmbivalentPair(2, 1))
516+
/// );
517+
/// assert_eq!(
518+
/// bh.hash_one(OrderAmbivalentPair(10, 2)),
519+
/// bh.hash_one(&OrderAmbivalentPair(2, 10))
520+
/// );
521+
/// ```
522+
#[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")]
523+
fn hash_one<T: Hash>(&self, x: T) -> u64 {
524+
let mut hasher = self.build_hasher();
525+
x.hash(&mut hasher);
526+
hasher.finish()
527+
}
484528
}
485529

486530
/// Used to create a default [`BuildHasher`] instance for types that implement

0 commit comments

Comments
 (0)