Skip to content

Commit

Permalink
Auto merge of #533 - Amanieu:default-hasher, r=Amanieu
Browse files Browse the repository at this point in the history
Replace "ahash" with "default-hasher" in Cargo features

This allows us to change the default hasher in the future without it being a breaking change.
  • Loading branch information
bors committed Jun 19, 2024
2 parents f0eece4 + 268414b commit 4c824c5
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 195 deletions.
20 changes: 14 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ serde = { version = "1.0.25", default-features = false, optional = true }
rkyv = { version = "0.7.42", optional = true, default-features = false, features = [
"alloc",
] }
borsh = { version = "1.5.0", default-features = false, optional = true, features = ["derive"]}

# When built as part of libstd
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
Expand All @@ -36,9 +37,6 @@ allocator-api2 = { version = "0.2.9", optional = true, default-features = false,
# Equivalent trait which can be shared with other hash table implementations.
equivalent = { version = "1.0", optional = true, default-features = false }

# borsh serde
borsh = { version = "1.5.0", default-features = false, optional = true, features = ["derive"]}

[dev-dependencies]
lazy_static = "1.4"
rand = { version = "0.8.3", features = ["small_rng"] }
Expand All @@ -50,27 +48,37 @@ bumpalo = { version = "3.13.0", features = ["allocator-api2"] }
rkyv = { version = "0.7.42", features = ["validation"] }

[features]
default = ["ahash", "inline-more", "allocator-api2", "equivalent"]
default = ["default-hasher", "inline-more", "allocator-api2", "equivalent"]

# Enables use of nightly features. This is only guaranteed to work on the latest
# version of nightly Rust.
nightly = ["allocator-api2?/nightly", "bumpalo/allocator_api"]

# Enables the RustcEntry API used to provide the standard library's Entry API.
rustc-internal-api = []

# Internal feature used when building as part of the standard library.
rustc-dep-of-std = [
"nightly",
"core",
"compiler_builtins",
"alloc",
"rustc-internal-api",
]

# Enables the RawTable API.
raw = []

# Provides a default hasher. Currently this is AHash but this is subject to
# change in the future. Note that the default hasher does *not* provide HashDoS
# resistance, unlike the one in the standard library.
default-hasher = ["dep:ahash"]

# Enables usage of `#[inline]` on far more functions than by default in this
# crate. This may lead to a performance increase but often comes at a compile
# time cost.
inline-more = []

borsh = ["dep:borsh"]

[package.metadata.docs.rs]
features = ["nightly", "rayon", "serde", "raw"]
rustdoc-args = ["--generate-link-to-definition"]
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,14 @@ This crate has the following Cargo features:

- `nightly`: Enables nightly-only features including: `#[may_dangle]`.
- `serde`: Enables serde serialization support.
- `borsh`: Enables borsh serialization support.
- `rkyv`: Enables rkyv serialization support.
- `rayon`: Enables rayon parallel iterator support.
- `equivalent`: Allows comparisons to be customized with the `Equivalent` trait.
- `raw`: Enables access to the experimental and unsafe `RawTable` API.
- `inline-more`: Adds inline hints to most functions, improving run-time performance at the cost
of compilation time. (enabled by default)
- `ahash`: Compiles with ahash as default hasher. (enabled by default)
- `default-hasher`: Compiles with ahash as default hasher. (enabled by default)
- `allocator-api2`: Enables support for allocators that support `allocator-api2`. (enabled by default)

## License
Expand Down
2 changes: 1 addition & 1 deletion benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extern crate test;

use test::{black_box, Bencher};

use hashbrown::hash_map::DefaultHashBuilder;
use hashbrown::DefaultHashBuilder;
use hashbrown::{HashMap, HashSet};
use std::{
collections::hash_map::RandomState,
Expand Down
5 changes: 1 addition & 4 deletions src/external_trait_impls/rayon/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,7 @@ mod test_par_table {

use rayon::prelude::*;

use crate::{
hash_map::{make_hash, DefaultHashBuilder},
hash_table::HashTable,
};
use crate::{hash_map::make_hash, hash_table::HashTable, DefaultHashBuilder};

#[test]
fn test_iterate() {
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
#![cfg_attr(feature = "nightly", warn(fuzzy_provenance_casts))]
#![cfg_attr(feature = "nightly", allow(internal_features))]

/// Default hasher for [`HashMap`], [`HashSet`] and [`HashTable`].
#[cfg(feature = "default-hasher")]
pub type DefaultHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;

/// Dummy default hasher for [`HashMap`], [`HashSet`] and [`HashTable`].
#[cfg(not(feature = "default-hasher"))]
pub enum DefaultHashBuilder {}

#[cfg(test)]
#[macro_use]
extern crate std;
Expand Down
27 changes: 9 additions & 18 deletions src/map.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::raw::{
Allocator, Bucket, Global, RawDrain, RawExtractIf, RawIntoIter, RawIter, RawTable,
};
use crate::{Equivalent, TryReserveError};
use crate::{DefaultHashBuilder, Equivalent, TryReserveError};
use core::borrow::Borrow;
use core::fmt::{self, Debug};
use core::hash::{BuildHasher, Hash};
Expand All @@ -10,14 +10,6 @@ use core::marker::PhantomData;
use core::mem;
use core::ops::Index;

/// Default hasher for `HashMap`.
#[cfg(feature = "ahash")]
pub type DefaultHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;

/// Dummy default hasher for `HashMap`.
#[cfg(not(feature = "ahash"))]
pub enum DefaultHashBuilder {}

/// A hash map implemented with quadratic probing and SIMD lookup.
///
/// The default hashing algorithm is currently [`AHash`], though this is
Expand Down Expand Up @@ -262,7 +254,7 @@ where
hash_builder.hash_one(val)
}

#[cfg(feature = "ahash")]
#[cfg(feature = "default-hasher")]
impl<K, V> HashMap<K, V, DefaultHashBuilder> {
/// Creates an empty `HashMap`.
///
Expand Down Expand Up @@ -325,7 +317,7 @@ impl<K, V> HashMap<K, V, DefaultHashBuilder> {
}
}

#[cfg(feature = "ahash")]
#[cfg(feature = "default-hasher")]
impl<K, V, A: Allocator> HashMap<K, V, DefaultHashBuilder, A> {
/// Creates an empty `HashMap` using the given allocator.
///
Expand Down Expand Up @@ -447,7 +439,7 @@ impl<K, V, S> HashMap<K, V, S> {
///
/// ```
/// use hashbrown::HashMap;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut map = HashMap::with_hasher(s);
Expand Down Expand Up @@ -489,7 +481,7 @@ impl<K, V, S> HashMap<K, V, S> {
///
/// ```
/// use hashbrown::HashMap;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
Expand Down Expand Up @@ -535,7 +527,7 @@ impl<K, V, S, A: Allocator> HashMap<K, V, S, A> {
///
/// ```
/// use hashbrown::HashMap;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut map = HashMap::with_hasher(s);
Expand Down Expand Up @@ -570,7 +562,7 @@ impl<K, V, S, A: Allocator> HashMap<K, V, S, A> {
///
/// ```
/// use hashbrown::HashMap;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
Expand All @@ -592,7 +584,7 @@ impl<K, V, S, A: Allocator> HashMap<K, V, S, A> {
///
/// ```
/// use hashbrown::HashMap;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let hasher = DefaultHashBuilder::default();
/// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
Expand Down Expand Up @@ -2258,7 +2250,7 @@ where
}

// The default hasher is used to match the std implementation signature
#[cfg(feature = "ahash")]
#[cfg(feature = "default-hasher")]
impl<K, V, A, const N: usize> From<[(K, V); N]> for HashMap<K, V, DefaultHashBuilder, A>
where
K: Eq + Hash,
Expand Down Expand Up @@ -6726,7 +6718,6 @@ mod test_map {
use rand::{rngs::SmallRng, Rng, SeedableRng};
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::usize;
use std::vec::Vec;

#[test]
Expand Down
14 changes: 7 additions & 7 deletions src/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ impl<T> Bucket<T> {
/// use core::hash::{BuildHasher, Hash};
/// use hashbrown::raw::{Bucket, RawTable};
///
/// type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;
/// type NewHashBuilder = hashbrown::DefaultHashBuilder;
///
/// fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
/// use core::hash::Hasher;
Expand Down Expand Up @@ -649,7 +649,7 @@ impl<T> Bucket<T> {
/// use core::hash::{BuildHasher, Hash};
/// use hashbrown::raw::{Bucket, RawTable};
///
/// type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;
/// type NewHashBuilder = hashbrown::DefaultHashBuilder;
///
/// fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
/// use core::hash::Hasher;
Expand Down Expand Up @@ -708,7 +708,7 @@ impl<T> Bucket<T> {
/// use core::hash::{BuildHasher, Hash};
/// use hashbrown::raw::{Bucket, RawTable};
///
/// type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;
/// type NewHashBuilder = hashbrown::DefaultHashBuilder;
///
/// fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
/// use core::hash::Hasher;
Expand Down Expand Up @@ -1235,7 +1235,7 @@ impl<T, A: Allocator> RawTable<T, A> {
fallibility,
Self::TABLE_LAYOUT,
if T::NEEDS_DROP {
Some(mem::transmute(ptr::drop_in_place::<T> as unsafe fn(*mut T)))
Some(|ptr| ptr::drop_in_place(ptr as *mut T))
} else {
None
},
Expand Down Expand Up @@ -2911,7 +2911,7 @@ impl RawTableInner {
hasher: &dyn Fn(&mut Self, usize) -> u64,
fallibility: Fallibility,
layout: TableLayout,
drop: Option<fn(*mut u8)>,
drop: Option<unsafe fn(*mut u8)>,
) -> Result<(), TryReserveError>
where
A: Allocator,
Expand Down Expand Up @@ -3145,7 +3145,7 @@ impl RawTableInner {
&mut self,
hasher: &dyn Fn(&mut Self, usize) -> u64,
size_of: usize,
drop: Option<fn(*mut u8)>,
drop: Option<unsafe fn(*mut u8)>,
) {
// If the hash function panics then properly clean up any elements
// that we haven't rehashed yet. We unfortunately can't preserve the
Expand Down Expand Up @@ -4577,7 +4577,7 @@ mod test_map {
&|table, index| hasher(table.bucket::<T>(index).as_ref()),
mem::size_of::<T>(),
if mem::needs_drop::<T>() {
Some(mem::transmute(ptr::drop_in_place::<T> as unsafe fn(*mut T)))
Some(|ptr| ptr::drop_in_place(ptr as *mut T))
} else {
None
},
Expand Down
21 changes: 11 additions & 10 deletions src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use core::hash::{BuildHasher, Hash};
use core::iter::{Chain, FusedIterator};
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign};

use super::map::{self, DefaultHashBuilder, HashMap, Keys};
use super::map::{self, HashMap, Keys};
use crate::raw::{Allocator, Global, RawExtractIf};
use crate::DefaultHashBuilder;

// Future Optimization (FIXME!)
// =============================
Expand Down Expand Up @@ -128,7 +129,7 @@ impl<T: Clone, S: Clone, A: Allocator + Clone> Clone for HashSet<T, S, A> {
}
}

#[cfg(feature = "ahash")]
#[cfg(feature = "default-hasher")]
impl<T> HashSet<T, DefaultHashBuilder> {
/// Creates an empty `HashSet`.
///
Expand Down Expand Up @@ -192,7 +193,7 @@ impl<T> HashSet<T, DefaultHashBuilder> {
}
}

#[cfg(feature = "ahash")]
#[cfg(feature = "default-hasher")]
impl<T: Hash + Eq, A: Allocator> HashSet<T, DefaultHashBuilder, A> {
/// Creates an empty `HashSet`.
///
Expand Down Expand Up @@ -459,7 +460,7 @@ impl<T, S> HashSet<T, S, Global> {
///
/// ```
/// use hashbrown::HashSet;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut set = HashSet::with_hasher(s);
Expand Down Expand Up @@ -497,7 +498,7 @@ impl<T, S> HashSet<T, S, Global> {
///
/// ```
/// use hashbrown::HashSet;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut set = HashSet::with_capacity_and_hasher(10, s);
Expand Down Expand Up @@ -546,7 +547,7 @@ where
///
/// ```
/// use hashbrown::HashSet;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut set = HashSet::with_hasher(s);
Expand Down Expand Up @@ -584,7 +585,7 @@ where
///
/// ```
/// use hashbrown::HashSet;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let s = DefaultHashBuilder::default();
/// let mut set = HashSet::with_capacity_and_hasher(10, s);
Expand All @@ -605,7 +606,7 @@ where
///
/// ```
/// use hashbrown::HashSet;
/// use hashbrown::hash_map::DefaultHashBuilder;
/// use hashbrown::DefaultHashBuilder;
///
/// let hasher = DefaultHashBuilder::default();
/// let set: HashSet<i32> = HashSet::with_hasher(hasher);
Expand Down Expand Up @@ -1324,7 +1325,7 @@ where
}

// The default hasher is used to match the std implementation signature
#[cfg(feature = "ahash")]
#[cfg(feature = "default-hasher")]
impl<T, A, const N: usize> From<[T; N]> for HashSet<T, DefaultHashBuilder, A>
where
T: Eq + Hash,
Expand Down Expand Up @@ -2643,8 +2644,8 @@ fn assert_covariance() {

#[cfg(test)]
mod test_set {
use super::super::map::DefaultHashBuilder;
use super::HashSet;
use crate::DefaultHashBuilder;
use std::vec::Vec;

#[test]
Expand Down
Loading

0 comments on commit 4c824c5

Please sign in to comment.