Skip to content

Commit 075409d

Browse files
committed
Move RandomState and DefaultHasher into std::hash, but don't export for now
1 parent a2f5f96 commit 075409d

File tree

12 files changed

+272
-168
lines changed

12 files changed

+272
-168
lines changed

Diff for: library/std/src/collections/hash/map.rs

+1-150
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@ use self::Entry::*;
66
use hashbrown::hash_map as base;
77

88
use crate::borrow::Borrow;
9-
use crate::cell::Cell;
109
use crate::collections::TryReserveError;
1110
use crate::collections::TryReserveErrorKind;
1211
use crate::error::Error;
1312
use crate::fmt::{self, Debug};
14-
#[allow(deprecated)]
15-
use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13};
13+
use crate::hash::{BuildHasher, Hash, RandomState};
1614
use crate::iter::FusedIterator;
1715
use crate::ops::Index;
18-
use crate::sys;
1916

2017
/// A [hash map] implemented with quadratic probing and SIMD lookup.
2118
///
@@ -3072,152 +3069,6 @@ where
30723069
}
30733070
}
30743071

3075-
/// `RandomState` is the default state for [`HashMap`] types.
3076-
///
3077-
/// A particular instance `RandomState` will create the same instances of
3078-
/// [`Hasher`], but the hashers created by two different `RandomState`
3079-
/// instances are unlikely to produce the same result for the same values.
3080-
///
3081-
/// # Examples
3082-
///
3083-
/// ```
3084-
/// use std::collections::HashMap;
3085-
/// use std::collections::hash_map::RandomState;
3086-
///
3087-
/// let s = RandomState::new();
3088-
/// let mut map = HashMap::with_hasher(s);
3089-
/// map.insert(1, 2);
3090-
/// ```
3091-
#[derive(Clone)]
3092-
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
3093-
pub struct RandomState {
3094-
k0: u64,
3095-
k1: u64,
3096-
}
3097-
3098-
impl RandomState {
3099-
/// Constructs a new `RandomState` that is initialized with random keys.
3100-
///
3101-
/// # Examples
3102-
///
3103-
/// ```
3104-
/// use std::collections::hash_map::RandomState;
3105-
///
3106-
/// let s = RandomState::new();
3107-
/// ```
3108-
#[inline]
3109-
#[allow(deprecated)]
3110-
// rand
3111-
#[must_use]
3112-
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
3113-
pub fn new() -> RandomState {
3114-
// Historically this function did not cache keys from the OS and instead
3115-
// simply always called `rand::thread_rng().gen()` twice. In #31356 it
3116-
// was discovered, however, that because we re-seed the thread-local RNG
3117-
// from the OS periodically that this can cause excessive slowdown when
3118-
// many hash maps are created on a thread. To solve this performance
3119-
// trap we cache the first set of randomly generated keys per-thread.
3120-
//
3121-
// Later in #36481 it was discovered that exposing a deterministic
3122-
// iteration order allows a form of DOS attack. To counter that we
3123-
// increment one of the seeds on every RandomState creation, giving
3124-
// every corresponding HashMap a different iteration order.
3125-
thread_local!(static KEYS: Cell<(u64, u64)> = {
3126-
Cell::new(sys::hashmap_random_keys())
3127-
});
3128-
3129-
KEYS.with(|keys| {
3130-
let (k0, k1) = keys.get();
3131-
keys.set((k0.wrapping_add(1), k1));
3132-
RandomState { k0, k1 }
3133-
})
3134-
}
3135-
}
3136-
3137-
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
3138-
impl BuildHasher for RandomState {
3139-
type Hasher = DefaultHasher;
3140-
#[inline]
3141-
#[allow(deprecated)]
3142-
fn build_hasher(&self) -> DefaultHasher {
3143-
DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1))
3144-
}
3145-
}
3146-
3147-
/// The default [`Hasher`] used by [`RandomState`].
3148-
///
3149-
/// The internal algorithm is not specified, and so it and its hashes should
3150-
/// not be relied upon over releases.
3151-
#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
3152-
#[allow(deprecated)]
3153-
#[derive(Clone, Debug)]
3154-
pub struct DefaultHasher(SipHasher13);
3155-
3156-
impl DefaultHasher {
3157-
/// Creates a new `DefaultHasher`.
3158-
///
3159-
/// This hasher is not guaranteed to be the same as all other
3160-
/// `DefaultHasher` instances, but is the same as all other `DefaultHasher`
3161-
/// instances created through `new` or `default`.
3162-
#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
3163-
#[inline]
3164-
#[allow(deprecated)]
3165-
#[rustc_const_unstable(feature = "const_hash", issue = "104061")]
3166-
#[must_use]
3167-
pub const fn new() -> DefaultHasher {
3168-
DefaultHasher(SipHasher13::new_with_keys(0, 0))
3169-
}
3170-
}
3171-
3172-
#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
3173-
impl Default for DefaultHasher {
3174-
/// Creates a new `DefaultHasher` using [`new`].
3175-
/// See its documentation for more.
3176-
///
3177-
/// [`new`]: DefaultHasher::new
3178-
#[inline]
3179-
fn default() -> DefaultHasher {
3180-
DefaultHasher::new()
3181-
}
3182-
}
3183-
3184-
#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
3185-
impl Hasher for DefaultHasher {
3186-
// The underlying `SipHasher13` doesn't override the other
3187-
// `write_*` methods, so it's ok not to forward them here.
3188-
3189-
#[inline]
3190-
fn write(&mut self, msg: &[u8]) {
3191-
self.0.write(msg)
3192-
}
3193-
3194-
#[inline]
3195-
fn write_str(&mut self, s: &str) {
3196-
self.0.write_str(s);
3197-
}
3198-
3199-
#[inline]
3200-
fn finish(&self) -> u64 {
3201-
self.0.finish()
3202-
}
3203-
}
3204-
3205-
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
3206-
impl Default for RandomState {
3207-
/// Constructs a new `RandomState`.
3208-
#[inline]
3209-
fn default() -> RandomState {
3210-
RandomState::new()
3211-
}
3212-
}
3213-
3214-
#[stable(feature = "std_debug", since = "1.16.0")]
3215-
impl fmt::Debug for RandomState {
3216-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3217-
f.debug_struct("RandomState").finish_non_exhaustive()
3218-
}
3219-
}
3220-
32213072
#[inline]
32223073
fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, V> {
32233074
match raw {

Diff for: library/std/src/collections/hash/map/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::Entry::{Occupied, Vacant};
22
use super::HashMap;
3-
use super::RandomState;
43
use crate::assert_matches::assert_matches;
54
use crate::cell::RefCell;
5+
use crate::hash::RandomState;
66
use crate::test_helpers::test_rng;
77
use rand::Rng;
88
use realstd::collections::TryReserveErrorKind::*;

Diff for: library/std/src/collections/hash/set.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ use hashbrown::hash_set as base;
66
use crate::borrow::Borrow;
77
use crate::collections::TryReserveError;
88
use crate::fmt;
9-
use crate::hash::{BuildHasher, Hash};
9+
use crate::hash::{BuildHasher, Hash, RandomState};
1010
use crate::iter::{Chain, FusedIterator};
1111
use crate::ops::{BitAnd, BitOr, BitXor, Sub};
1212

13-
use super::map::{map_try_reserve_error, RandomState};
13+
use super::map::map_try_reserve_error;
1414

1515
/// A [hash set] implemented as a `HashMap` where the value is `()`.
1616
///

Diff for: library/std/src/collections/hash/set/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use super::super::map::RandomState;
21
use super::HashSet;
32

3+
use crate::hash::RandomState;
44
use crate::panic::{catch_unwind, AssertUnwindSafe};
55
use crate::sync::atomic::{AtomicU32, Ordering};
66
use crate::sync::Arc;

Diff for: library/std/src/collections/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,11 @@ pub mod hash_map {
439439
//! A hash map implemented with quadratic probing and SIMD lookup.
440440
#[stable(feature = "rust1", since = "1.0.0")]
441441
pub use super::hash::map::*;
442+
443+
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
444+
pub use crate::hash::random::DefaultHasher;
445+
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
446+
pub use crate::hash::random::RandomState;
442447
}
443448

444449
#[stable(feature = "rust1", since = "1.0.0")]

Diff for: library/std/src/hash/mod.rs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//! Generic hashing support.
2+
//!
3+
//! This module provides a generic way to compute the [hash] of a value.
4+
//! Hashes are most commonly used with [`HashMap`] and [`HashSet`].
5+
//!
6+
//! [hash]: https://en.wikipedia.org/wiki/Hash_function
7+
//! [`HashMap`]: ../../std/collections/struct.HashMap.html
8+
//! [`HashSet`]: ../../std/collections/struct.HashSet.html
9+
//!
10+
//! The simplest way to make a type hashable is to use `#[derive(Hash)]`:
11+
//!
12+
//! # Examples
13+
//!
14+
//! ```rust
15+
//! use std::hash::{DefaultHasher, Hash, Hasher};
16+
//!
17+
//! #[derive(Hash)]
18+
//! struct Person {
19+
//! id: u32,
20+
//! name: String,
21+
//! phone: u64,
22+
//! }
23+
//!
24+
//! let person1 = Person {
25+
//! id: 5,
26+
//! name: "Janet".to_string(),
27+
//! phone: 555_666_7777,
28+
//! };
29+
//! let person2 = Person {
30+
//! id: 5,
31+
//! name: "Bob".to_string(),
32+
//! phone: 555_666_7777,
33+
//! };
34+
//!
35+
//! assert!(calculate_hash(&person1) != calculate_hash(&person2));
36+
//!
37+
//! fn calculate_hash<T: Hash>(t: &T) -> u64 {
38+
//! let mut s = DefaultHasher::new();
39+
//! t.hash(&mut s);
40+
//! s.finish()
41+
//! }
42+
//! ```
43+
//!
44+
//! If you need more control over how a value is hashed, you need to implement
45+
//! the [`Hash`] trait:
46+
//!
47+
//! ```rust
48+
//! use std::hash::{DefaultHasher, Hash, Hasher};
49+
//!
50+
//! struct Person {
51+
//! id: u32,
52+
//! # #[allow(dead_code)]
53+
//! name: String,
54+
//! phone: u64,
55+
//! }
56+
//!
57+
//! impl Hash for Person {
58+
//! fn hash<H: Hasher>(&self, state: &mut H) {
59+
//! self.id.hash(state);
60+
//! self.phone.hash(state);
61+
//! }
62+
//! }
63+
//!
64+
//! let person1 = Person {
65+
//! id: 5,
66+
//! name: "Janet".to_string(),
67+
//! phone: 555_666_7777,
68+
//! };
69+
//! let person2 = Person {
70+
//! id: 5,
71+
//! name: "Bob".to_string(),
72+
//! phone: 555_666_7777,
73+
//! };
74+
//!
75+
//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2));
76+
//!
77+
//! fn calculate_hash<T: Hash>(t: &T) -> u64 {
78+
//! let mut s = DefaultHasher::new();
79+
//! t.hash(&mut s);
80+
//! s.finish()
81+
//! }
82+
//! ```
83+
#![stable(feature = "rust1", since = "1.0.0")]
84+
85+
pub(crate) mod random;
86+
87+
#[stable(feature = "rust1", since = "1.0.0")]
88+
pub use core::hash::*;
89+
90+
// #[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")]
91+
pub(crate) use self::random::{DefaultHasher, RandomState};

0 commit comments

Comments
 (0)