Skip to content

Commit 26ef4a1

Browse files
committed
Remove the raw feature and make RawTable private
This will give more freedom for the internal implementation details of hashbrown to evolve without the need for regular releases with breaking changes. All existing users of `RawTable` should migrate to the `HashTable` API which is entirely safe while providing the same flexibility as `RawTable`. This also removes the following features which were only exposed under `RawTable`: - `RawTable::iter_hash` - `RawIter::reflect_insert` and `RawIter::reflect_remove` - `RawTable::clone_from_with_hasher` - `RawTable::insert_no_grow` and `RawTable::try_insert_no_grow` - `RawTable::allocation_info` - `RawTable::try_with_capacity(_in)` - `HashMap::raw_table(_mut)` and `HashSet::raw_table(_mut)`
1 parent f01e271 commit 26ef4a1

File tree

10 files changed

+4
-807
lines changed

10 files changed

+4
-807
lines changed

Diff for: Cargo.toml

+1-4
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ rustc-dep-of-std = [
6767
"raw-entry",
6868
]
6969

70-
# Enables the experimental and unsafe RawTable API.
71-
raw = []
72-
7370
# Enables the deprecated RawEntry API.
7471
raw-entry = []
7572

@@ -84,5 +81,5 @@ default-hasher = ["dep:ahash"]
8481
inline-more = []
8582

8683
[package.metadata.docs.rs]
87-
features = ["nightly", "rayon", "serde", "raw"]
84+
features = ["nightly", "rayon", "serde", "raw-entry"]
8885
rustdoc-args = ["--generate-link-to-definition"]

Diff for: README.md

-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ This crate has the following Cargo features:
105105
- `rkyv`: Enables rkyv serialization support.
106106
- `rayon`: Enables rayon parallel iterator support.
107107
- `equivalent`: Allows comparisons to be customized with the `Equivalent` trait.
108-
- `raw`: Enables access to the experimental and unsafe `RawTable` API.
109108
- `raw-entry`: Enables access to the deprecated `RawEntry` API.
110109
- `inline-more`: Adds inline hints to most functions, improving run-time performance at the cost
111110
of compilation time. (enabled by default)

Diff for: ci/run.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ if [ "${NO_STD}" = "1" ]; then
3333
FEATURES="rustc-internal-api"
3434
OP="build"
3535
else
36-
FEATURES="rustc-internal-api,serde,rayon,raw"
36+
FEATURES="rustc-internal-api,serde,rayon"
3737
OP="test"
3838
fi
3939

Diff for: ci/tools.sh

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ fi
3131

3232
if retry rustup component add clippy ; then
3333
cargo clippy --all --tests --features serde,rayon -- -D clippy::all
34-
cargo clippy --all --tests --features raw -- -D clippy::all
3534
fi
3635

3736
if command -v shellcheck ; then

Diff for: src/lib.rs

-21
Original file line numberDiff line numberDiff line change
@@ -61,27 +61,6 @@ doc_comment::doctest!("../README.md");
6161
#[macro_use]
6262
mod macros;
6363

64-
#[cfg(feature = "raw")]
65-
/// Experimental and unsafe `RawTable` API. This module is only available if the
66-
/// `raw` feature is enabled.
67-
pub mod raw {
68-
// The RawTable API is still experimental and is not properly documented yet.
69-
#[allow(missing_docs)]
70-
#[path = "mod.rs"]
71-
mod inner;
72-
pub use inner::*;
73-
74-
#[cfg(feature = "rayon")]
75-
/// [rayon]-based parallel iterator types for hash maps.
76-
/// You will rarely need to interact with it directly unless you have need
77-
/// to name one of the iterator types.
78-
///
79-
/// [rayon]: https://docs.rs/rayon/1.0/rayon
80-
pub mod rayon {
81-
pub use crate::external_trait_impls::rayon::raw::*;
82-
}
83-
}
84-
#[cfg(not(feature = "raw"))]
8564
mod raw;
8665

8766
mod external_trait_impls;

Diff for: src/map.rs

-143
Original file line numberDiff line numberDiff line change
@@ -1933,81 +1933,6 @@ where
19331933
}
19341934
}
19351935

1936-
impl<K, V, S, A: Allocator> HashMap<K, V, S, A> {
1937-
/// Returns a reference to the [`RawTable`] used underneath [`HashMap`].
1938-
/// This function is only available if the `raw` feature of the crate is enabled.
1939-
///
1940-
/// See [`raw_table_mut`] for more.
1941-
///
1942-
/// [`raw_table_mut`]: Self::raw_table_mut
1943-
#[cfg(feature = "raw")]
1944-
#[cfg_attr(feature = "inline-more", inline)]
1945-
pub fn raw_table(&self) -> &RawTable<(K, V), A> {
1946-
&self.table
1947-
}
1948-
1949-
/// Returns a mutable reference to the [`RawTable`] used underneath [`HashMap`].
1950-
/// This function is only available if the `raw` feature of the crate is enabled.
1951-
///
1952-
/// # Note
1953-
///
1954-
/// Calling this function is safe, but using the raw hash table API may require
1955-
/// unsafe functions or blocks.
1956-
///
1957-
/// `RawTable` API gives the lowest level of control under the map that can be useful
1958-
/// for extending the HashMap's API, but may lead to *[undefined behavior]*.
1959-
///
1960-
/// [`HashMap`]: struct.HashMap.html
1961-
/// [`RawTable`]: crate::raw::RawTable
1962-
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1963-
///
1964-
/// # Examples
1965-
///
1966-
/// ```
1967-
/// use core::hash::{BuildHasher, Hash};
1968-
/// use hashbrown::HashMap;
1969-
///
1970-
/// let mut map = HashMap::new();
1971-
/// map.extend([("a", 10), ("b", 20), ("c", 30)]);
1972-
/// assert_eq!(map.len(), 3);
1973-
///
1974-
/// // Let's imagine that we have a value and a hash of the key, but not the key itself.
1975-
/// // However, if you want to remove the value from the map by hash and value, and you
1976-
/// // know exactly that the value is unique, then you can create a function like this:
1977-
/// fn remove_by_hash<K, V, S, F>(
1978-
/// map: &mut HashMap<K, V, S>,
1979-
/// hash: u64,
1980-
/// is_match: F,
1981-
/// ) -> Option<(K, V)>
1982-
/// where
1983-
/// F: Fn(&(K, V)) -> bool,
1984-
/// {
1985-
/// let raw_table = map.raw_table_mut();
1986-
/// match raw_table.find(hash, is_match) {
1987-
/// Some(bucket) => Some(unsafe { raw_table.remove(bucket).0 }),
1988-
/// None => None,
1989-
/// }
1990-
/// }
1991-
///
1992-
/// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
1993-
/// use core::hash::Hasher;
1994-
/// let mut state = hash_builder.build_hasher();
1995-
/// key.hash(&mut state);
1996-
/// state.finish()
1997-
/// }
1998-
///
1999-
/// let hash = compute_hash(map.hasher(), "a");
2000-
/// assert_eq!(remove_by_hash(&mut map, hash, |(_, v)| *v == 10), Some(("a", 10)));
2001-
/// assert_eq!(map.get(&"a"), None);
2002-
/// assert_eq!(map.len(), 2);
2003-
/// ```
2004-
#[cfg(feature = "raw")]
2005-
#[cfg_attr(feature = "inline-more", inline)]
2006-
pub fn raw_table_mut(&mut self) -> &mut RawTable<(K, V), A> {
2007-
&mut self.table
2008-
}
2009-
}
2010-
20111936
impl<K, V, S, A> PartialEq for HashMap<K, V, S, A>
20121937
where
20131938
K: Eq + Hash,
@@ -6699,74 +6624,6 @@ mod test_map {
66996624
}
67006625
}
67016626

6702-
#[test]
6703-
#[cfg(feature = "raw")]
6704-
fn test_into_iter_refresh() {
6705-
#[cfg(miri)]
6706-
const N: usize = 32;
6707-
#[cfg(not(miri))]
6708-
const N: usize = 128;
6709-
6710-
let mut rng = rand::thread_rng();
6711-
for n in 0..N {
6712-
let mut map = HashMap::new();
6713-
for i in 0..n {
6714-
assert!(map.insert(i, 2 * i).is_none());
6715-
}
6716-
let hash_builder = map.hasher().clone();
6717-
6718-
let mut it = unsafe { map.table.iter() };
6719-
assert_eq!(it.len(), n);
6720-
6721-
let mut i = 0;
6722-
let mut left = n;
6723-
let mut removed = Vec::new();
6724-
loop {
6725-
// occasionally remove some elements
6726-
if i < n && rng.gen_bool(0.1) {
6727-
let hash_value = super::make_hash(&hash_builder, &i);
6728-
6729-
unsafe {
6730-
let e = map.table.find(hash_value, |q| q.0.eq(&i));
6731-
if let Some(e) = e {
6732-
it.reflect_remove(&e);
6733-
let t = map.table.remove(e).0;
6734-
removed.push(t);
6735-
left -= 1;
6736-
} else {
6737-
assert!(removed.contains(&(i, 2 * i)), "{i} not in {removed:?}");
6738-
let e = map.table.insert(
6739-
hash_value,
6740-
(i, 2 * i),
6741-
super::make_hasher::<_, usize, _>(&hash_builder),
6742-
);
6743-
it.reflect_insert(&e);
6744-
if let Some(p) = removed.iter().position(|e| e == &(i, 2 * i)) {
6745-
removed.swap_remove(p);
6746-
}
6747-
left += 1;
6748-
}
6749-
}
6750-
}
6751-
6752-
let e = it.next();
6753-
if e.is_none() {
6754-
break;
6755-
}
6756-
assert!(i < n);
6757-
let t = unsafe { e.unwrap().as_ref() };
6758-
assert!(!removed.contains(t));
6759-
let (key, value) = t;
6760-
assert_eq!(*value, 2 * key);
6761-
i += 1;
6762-
}
6763-
assert!(i <= n);
6764-
6765-
// just for safety:
6766-
assert_eq!(map.table.len(), left);
6767-
}
6768-
}
6769-
67706627
#[test]
67716628
fn test_const_with_hasher() {
67726629
use core::hash::BuildHasher;

Diff for: src/raw/bitmask.rs

-16
Original file line numberDiff line numberDiff line change
@@ -105,22 +105,6 @@ impl IntoIterator for BitMask {
105105
#[derive(Copy, Clone)]
106106
pub(crate) struct BitMaskIter(pub(crate) BitMask);
107107

108-
impl BitMaskIter {
109-
/// Flip the bit in the mask for the entry at the given index.
110-
///
111-
/// Returns the bit's previous state.
112-
#[inline]
113-
#[allow(clippy::cast_ptr_alignment)]
114-
#[cfg(feature = "raw")]
115-
pub(crate) unsafe fn flip(&mut self, index: usize) -> bool {
116-
// NOTE: The + BITMASK_STRIDE - 1 is to set the high bit.
117-
let mask = 1 << (index * BITMASK_STRIDE + BITMASK_STRIDE - 1);
118-
self.0 .0 ^= mask;
119-
// The bit was set if the bit is now 0.
120-
self.0 .0 & mask == 0
121-
}
122-
}
123-
124108
impl Iterator for BitMaskIter {
125109
type Item = usize;
126110

0 commit comments

Comments
 (0)