From 68068e453e23601c3834a24505f8c9081e84d4dd Mon Sep 17 00:00:00 2001 From: "Hans Elias B. Josephsen" Date: Fri, 28 Feb 2020 12:05:09 +0100 Subject: [PATCH] Parametrize map and set over allocator --- src/map.rs | 289 +++++++++++++++++++++++++++++++---------------- src/raw/alloc.rs | 11 +- src/raw/mod.rs | 52 ++++----- src/set.rs | 272 ++++++++++++++++++++++++++++++++------------ 4 files changed, 425 insertions(+), 199 deletions(-) diff --git a/src/map.rs b/src/map.rs index 0a996ce4e2..b144b4ecfd 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,4 +1,4 @@ -use crate::raw::{Bucket, Global, RawDrain, RawIntoIter, RawIter, RawTable}; +use crate::raw::{Bucket, AllocRef, Global, RawDrain, RawIntoIter, RawIter, RawTable}; use crate::CollectionAllocErr; use core::borrow::Borrow; use core::fmt::{self, Debug}; @@ -191,9 +191,9 @@ pub enum DefaultHashBuilder {} /// } /// ``` #[derive(Clone)] -pub struct HashMap { +pub struct HashMap { pub(crate) hash_builder: S, - pub(crate) table: RawTable<(K, V), Global>, + pub(crate) table: RawTable<(K, V), A>, } #[cfg_attr(feature = "inline-more", inline)] @@ -238,6 +238,27 @@ impl HashMap { } } +#[cfg(feature = "ahash")] +impl HashMap { + /// Creates an empty `HashMap` using the given allocator. + /// + /// The hash map is initially created with a capacity of 0, so it will not allocate until it + /// is first inserted into. + #[cfg_attr(feature = "inline-more", inline)] + pub fn new_in(alloc: A) -> Self { + Self::with_hasher_in(Default::default(), alloc) + } + + /// Creates an empty `HashMap` with the specified capacity using the given allocator. + /// + /// The hash map will be able to hold at least `capacity` elements without + /// reallocating. If `capacity` is 0, the hash map will not allocate. + #[cfg_attr(feature = "inline-more", inline)] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Self::with_capacity_and_hasher_in(capacity, DefaultHashBuilder::default(), alloc) + } +} + impl HashMap { /// Creates an empty `HashMap` which will use the given hash builder to hash /// keys. @@ -295,6 +316,65 @@ impl HashMap { table: RawTable::with_capacity(Global, capacity), } } +} + +impl HashMap { + /// Creates an empty `HashMap` which will use the given hash builder to hash + /// keys. It will be allocated with the given allocator. + /// + /// The created map has the default initial capacity. + /// + /// Warning: `hash_builder` is normally randomly generated, and + /// is designed to allow HashMaps to be resistant to attacks that + /// cause many collisions and very poor performance. Setting it + /// manually using this function can expose a DoS attack vector. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::DefaultHashBuilder; + /// + /// let s = DefaultHashBuilder::default(); + /// let mut map = HashMap::with_hasher(s); + /// map.insert(1, 2); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn with_hasher_in(hash_builder: S, alloc: A) -> Self { + Self { + hash_builder, + table: RawTable::new(alloc), + } + } + + /// Creates an empty `HashMap` with the specified capacity, using `hash_builder` + /// to hash the keys. It will be allocated with the given allocator. + /// + /// The hash map will be able to hold at least `capacity` elements without + /// reallocating. If `capacity` is 0, the hash map will not allocate. + /// + /// Warning: `hash_builder` is normally randomly generated, and + /// is designed to allow HashMaps to be resistant to attacks that + /// cause many collisions and very poor performance. Setting it + /// manually using this function can expose a DoS attack vector. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::DefaultHashBuilder; + /// + /// let s = DefaultHashBuilder::default(); + /// let mut map = HashMap::with_capacity_and_hasher(10, s); + /// map.insert(1, 2); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn with_capacity_and_hasher_in(capacity: usize, hash_builder: S, alloc: A) -> Self { + Self { + hash_builder, + table: RawTable::with_capacity(alloc, capacity), + } + } /// Returns a reference to the map's [`BuildHasher`]. /// @@ -527,7 +607,7 @@ impl HashMap { /// assert!(a.is_empty()); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn drain(&mut self) -> Drain<'_, K, V> { + pub fn drain(&mut self) -> Drain<'_, K, V, A> { // Here we tie the lifetime of self to the iter. unsafe { Drain { @@ -555,10 +635,11 @@ impl HashMap { } } -impl HashMap +impl HashMap where K: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { /// Reserves capacity for at least `additional` more elements to be inserted /// in the `HashMap`. The collection may reserve more space to avoid @@ -679,7 +760,7 @@ where /// assert_eq!(letters.get(&'y'), None); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> { + pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S, A> { let hash = make_hash(&self.hash_builder, &key); if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) { Entry::Occupied(OccupiedEntry { @@ -975,7 +1056,7 @@ where /// assert_eq!(drained.count(), 4); /// assert_eq!(map.len(), 4); /// ``` - pub fn drain_filter(&mut self, f: F) -> DrainFilter<'_, K, V, F> + pub fn drain_filter(&mut self, f: F) -> DrainFilter<'_, K, V, F, A> where F: FnMut(&K, &mut V) -> bool, { @@ -987,7 +1068,7 @@ where } } -impl HashMap { +impl HashMap { /// Creates a raw entry builder for the HashMap. /// /// Raw entries provide the lowest level of control for searching and @@ -1020,7 +1101,7 @@ impl HashMap { /// acting erratically, with two keys randomly masking each other. Implementations /// are free to assume this doesn't happen (within the limits of memory-safety). #[cfg_attr(feature = "inline-more", inline)] - pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { + pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S, A> { RawEntryBuilderMut { map: self } } @@ -1040,16 +1121,17 @@ impl HashMap { /// /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. #[cfg_attr(feature = "inline-more", inline)] - pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { + pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S, A> { RawEntryBuilder { map: self } } } -impl PartialEq for HashMap +impl PartialEq for HashMap where K: Eq + Hash, V: PartialEq, S: BuildHasher, + A: AllocRef + Clone, { fn eq(&self, other: &Self) -> bool { if self.len() != other.len() { @@ -1061,32 +1143,35 @@ where } } -impl Eq for HashMap +impl Eq for HashMap where K: Eq + Hash, V: Eq, S: BuildHasher, + A: AllocRef + Clone, { } -impl Debug for HashMap +impl Debug for HashMap where K: Debug, V: Debug, + A: AllocRef + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.iter()).finish() } } -impl Default for HashMap +impl Default for HashMap where S: Default, + A: Default + AllocRef + Clone, { - /// Creates an empty `HashMap`, with the `Default` value for the hasher. + /// Creates an empty `HashMap`, with the `Default` value for the hasher and allocator. #[cfg_attr(feature = "inline-more", inline)] fn default() -> Self { - Self::with_hasher(Default::default()) + Self::with_hasher_in(Default::default(), Default::default()) } } @@ -1174,11 +1259,11 @@ impl IterMut<'_, K, V> { /// /// [`into_iter`]: struct.HashMap.html#method.into_iter /// [`HashMap`]: struct.HashMap.html -pub struct IntoIter { - inner: RawIntoIter<(K, V), Global>, +pub struct IntoIter { + inner: RawIntoIter<(K, V), A>, } -impl IntoIter { +impl IntoIter { /// Returns a iterator of references over the remaining items. #[cfg_attr(feature = "inline-more", inline)] pub(super) fn iter(&self) -> Iter<'_, K, V> { @@ -1250,11 +1335,11 @@ impl fmt::Debug for Values<'_, K, V> { /// /// [`drain`]: struct.HashMap.html#method.drain /// [`HashMap`]: struct.HashMap.html -pub struct Drain<'a, K, V> { - inner: RawDrain<'a, (K, V), Global>, +pub struct Drain<'a, K, V, A: AllocRef + Clone = Global> { + inner: RawDrain<'a, (K, V), A>, } -impl Drain<'_, K, V> { +impl Drain<'_, K, V, A> { /// Returns a iterator of references over the remaining items. #[cfg_attr(feature = "inline-more", inline)] pub(super) fn iter(&self) -> Iter<'_, K, V> { @@ -1272,27 +1357,30 @@ impl Drain<'_, K, V> { /// /// [`drain_filter`]: struct.HashMap.html#method.drain_filter /// [`HashMap`]: struct.HashMap.html -pub struct DrainFilter<'a, K, V, F> +pub struct DrainFilter<'a, K, V, F, A: AllocRef + Clone> where F: FnMut(&K, &mut V) -> bool, { f: F, iter: RawIter<(K, V)>, - table: &'a mut RawTable<(K, V)>, + table: &'a mut RawTable<(K, V), A>, } -impl<'a, K, V, F> Drop for DrainFilter<'a, K, V, F> +impl<'a, K, V, F, A> Drop for DrainFilter<'a, K, V, F, A> where F: FnMut(&K, &mut V) -> bool, + A: AllocRef + Clone, { fn drop(&mut self) { - struct DropGuard<'r, 'a, K, V, F>(&'r mut DrainFilter<'a, K, V, F>) + struct DropGuard<'r, 'a, K, V, F, A>(&'r mut DrainFilter<'a, K, V, F, A>) where - F: FnMut(&K, &mut V) -> bool; + F: FnMut(&K, &mut V) -> bool, + A: AllocRef + Clone; - impl<'r, 'a, K, V, F> Drop for DropGuard<'r, 'a, K, V, F> + impl<'r, 'a, K, V, F, A> Drop for DropGuard<'r, 'a, K, V, F, A> where F: FnMut(&K, &mut V) -> bool, + A: AllocRef + Clone, { fn drop(&mut self) { while let Some(_) = self.0.next() {} @@ -1306,9 +1394,10 @@ where } } -impl Iterator for DrainFilter<'_, K, V, F> +impl Iterator for DrainFilter<'_, K, V, F, A> where F: FnMut(&K, &mut V) -> bool, + A: AllocRef + Clone, { type Item = (K, V); fn next(&mut self) -> Option { @@ -1341,8 +1430,8 @@ pub struct ValuesMut<'a, K, V> { /// See the [`HashMap::raw_entry_mut`] docs for usage examples. /// /// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut -pub struct RawEntryBuilderMut<'a, K, V, S> { - map: &'a mut HashMap, +pub struct RawEntryBuilderMut<'a, K, V, S, A: AllocRef + Clone> { + map: &'a mut HashMap, } /// A view into a single entry in a map, which may either be vacant or occupied. @@ -1356,32 +1445,34 @@ pub struct RawEntryBuilderMut<'a, K, V, S> { /// [`Entry`]: enum.Entry.html /// [`raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut /// [`RawEntryBuilderMut`]: struct.RawEntryBuilderMut.html -pub enum RawEntryMut<'a, K, V, S> { +pub enum RawEntryMut<'a, K, V, S, A: AllocRef + Clone> { /// An occupied entry. - Occupied(RawOccupiedEntryMut<'a, K, V>), + Occupied(RawOccupiedEntryMut<'a, K, V, A>), /// A vacant entry. - Vacant(RawVacantEntryMut<'a, K, V, S>), + Vacant(RawVacantEntryMut<'a, K, V, S, A>), } /// A view into an occupied entry in a `HashMap`. /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -pub struct RawOccupiedEntryMut<'a, K, V> { +pub struct RawOccupiedEntryMut<'a, K, V, A: AllocRef + Clone> { elem: Bucket<(K, V)>, - table: &'a mut RawTable<(K, V), Global>, + table: &'a mut RawTable<(K, V), A>, } -unsafe impl Send for RawOccupiedEntryMut<'_, K, V> +unsafe impl Send for RawOccupiedEntryMut<'_, K, V, A> where K: Send, V: Send, + A: Send + AllocRef + Clone, { } -unsafe impl Sync for RawOccupiedEntryMut<'_, K, V> +unsafe impl Sync for RawOccupiedEntryMut<'_, K, V, A> where K: Sync, V: Sync, + A: Send + AllocRef + Clone, { } @@ -1389,8 +1480,8 @@ where /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -pub struct RawVacantEntryMut<'a, K, V, S> { - table: &'a mut RawTable<(K, V), Global>, +pub struct RawVacantEntryMut<'a, K, V, S, A: AllocRef + Clone> { + table: &'a mut RawTable<(K, V), A>, hash_builder: &'a S, } @@ -1399,15 +1490,15 @@ pub struct RawVacantEntryMut<'a, K, V, S> { /// See the [`HashMap::raw_entry`] docs for usage examples. /// /// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry -pub struct RawEntryBuilder<'a, K, V, S> { - map: &'a HashMap, +pub struct RawEntryBuilder<'a, K, V, S, A: AllocRef + Clone> { + map: &'a HashMap, } -impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> RawEntryBuilderMut<'a, K, V, S, A> { /// Creates a `RawEntryMut` from the given key. #[cfg_attr(feature = "inline-more", inline)] #[allow(clippy::wrong_self_convention)] - pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> + pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S, A> where S: BuildHasher, K: Borrow, @@ -1421,7 +1512,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { /// Creates a `RawEntryMut` from the given key and its hash. #[inline] #[allow(clippy::wrong_self_convention)] - pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> + pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S, A> where K: Borrow, Q: Eq, @@ -1430,11 +1521,11 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { } } -impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> RawEntryBuilderMut<'a, K, V, S, A> { /// Creates a `RawEntryMut` from the given hash. #[cfg_attr(feature = "inline-more", inline)] #[allow(clippy::wrong_self_convention)] - pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> + pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S, A> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1442,7 +1533,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { } #[cfg_attr(feature = "inline-more", inline)] - fn search(self, hash: u64, mut is_match: F) -> RawEntryMut<'a, K, V, S> + fn search(self, hash: u64, mut is_match: F) -> RawEntryMut<'a, K, V, S, A> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1459,7 +1550,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { } } -impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> RawEntryBuilder<'a, K, V, S, A> { /// Access an entry by key. #[cfg_attr(feature = "inline-more", inline)] #[allow(clippy::wrong_self_convention)] @@ -1510,7 +1601,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> { } } -impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> RawEntryMut<'a, K, V, S, A> { /// Sets the value of the entry, and returns a RawOccupiedEntryMut. /// /// # Examples @@ -1524,7 +1615,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// assert_eq!(entry.remove_entry(), ("horseyland", 37)); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V> + pub fn insert(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, A> where K: Hash, S: BuildHasher, @@ -1638,7 +1729,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { } } -impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { +impl<'a, K, V, A: AllocRef + Clone> RawOccupiedEntryMut<'a, K, V, A> { /// Gets a reference to the key in the entry. #[cfg_attr(feature = "inline-more", inline)] pub fn key(&self) -> &K { @@ -1733,7 +1824,7 @@ impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { } } -impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> RawVacantEntryMut<'a, K, V, S, A> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. #[cfg_attr(feature = "inline-more", inline)] @@ -1780,7 +1871,7 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { } #[cfg_attr(feature = "inline-more", inline)] - fn insert_entry(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V> + fn insert_entry(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, A> where K: Hash, S: BuildHasher, @@ -1799,13 +1890,13 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { } } -impl Debug for RawEntryBuilderMut<'_, K, V, S> { +impl Debug for RawEntryBuilderMut<'_, K, V, S, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawEntryBuilder").finish() } } -impl Debug for RawEntryMut<'_, K, V, S> { +impl Debug for RawEntryMut<'_, K, V, S, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(), @@ -1814,7 +1905,7 @@ impl Debug for RawEntryMut<'_, K, V, S> { } } -impl Debug for RawOccupiedEntryMut<'_, K, V> { +impl Debug for RawOccupiedEntryMut<'_, K, V, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawOccupiedEntryMut") .field("key", self.key()) @@ -1823,13 +1914,13 @@ impl Debug for RawOccupiedEntryMut<'_, K, V> { } } -impl Debug for RawVacantEntryMut<'_, K, V, S> { +impl Debug for RawVacantEntryMut<'_, K, V, S, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawVacantEntryMut").finish() } } -impl Debug for RawEntryBuilder<'_, K, V, S> { +impl Debug for RawEntryBuilder<'_, K, V, S, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawEntryBuilder").finish() } @@ -1841,15 +1932,15 @@ impl Debug for RawEntryBuilder<'_, K, V, S> { /// /// [`HashMap`]: struct.HashMap.html /// [`entry`]: struct.HashMap.html#method.entry -pub enum Entry<'a, K, V, S> { +pub enum Entry<'a, K, V, S, A> where A: AllocRef + Clone { /// An occupied entry. - Occupied(OccupiedEntry<'a, K, V, S>), + Occupied(OccupiedEntry<'a, K, V, S, A>), /// A vacant entry. - Vacant(VacantEntry<'a, K, V, S>), + Vacant(VacantEntry<'a, K, V, S, A>), } -impl Debug for Entry<'_, K, V, S> { +impl Debug for Entry<'_, K, V, S, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), @@ -1862,28 +1953,30 @@ impl Debug for Entry<'_, K, V, S> { /// It is part of the [`Entry`] enum. /// /// [`Entry`]: enum.Entry.html -pub struct OccupiedEntry<'a, K, V, S> { +pub struct OccupiedEntry<'a, K, V, S, A> where A: AllocRef + Clone { key: Option, elem: Bucket<(K, V)>, - table: &'a mut HashMap, + table: &'a mut HashMap, } -unsafe impl Send for OccupiedEntry<'_, K, V, S> +unsafe impl Send for OccupiedEntry<'_, K, V, S, A> where K: Send, V: Send, S: Send, + A: Send + AllocRef + Clone, { } -unsafe impl Sync for OccupiedEntry<'_, K, V, S> +unsafe impl Sync for OccupiedEntry<'_, K, V, S, A> where K: Sync, V: Sync, S: Sync, + A: Sync + AllocRef + Clone, { } -impl Debug for OccupiedEntry<'_, K, V, S> { +impl Debug for OccupiedEntry<'_, K, V, S, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OccupiedEntry") .field("key", self.key()) @@ -1896,19 +1989,19 @@ impl Debug for OccupiedEntry<'_, K, V, S> { /// It is part of the [`Entry`] enum. /// /// [`Entry`]: enum.Entry.html -pub struct VacantEntry<'a, K, V, S> { +pub struct VacantEntry<'a, K, V, S, A> where A: AllocRef + Clone { hash: u64, key: K, - table: &'a mut HashMap, + table: &'a mut HashMap, } -impl Debug for VacantEntry<'_, K, V, S> { +impl Debug for VacantEntry<'_, K, V, S, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("VacantEntry").field(self.key()).finish() } } -impl<'a, K, V, S> IntoIterator for &'a HashMap { +impl<'a, K, V, S, A: AllocRef + Clone> IntoIterator for &'a HashMap { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; @@ -1918,7 +2011,7 @@ impl<'a, K, V, S> IntoIterator for &'a HashMap { } } -impl<'a, K, V, S> IntoIterator for &'a mut HashMap { +impl<'a, K, V, S, A: AllocRef + Clone> IntoIterator for &'a mut HashMap { type Item = (&'a K, &'a mut V); type IntoIter = IterMut<'a, K, V>; @@ -1928,9 +2021,9 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap { } } -impl IntoIterator for HashMap { +impl IntoIterator for HashMap { type Item = (K, V); - type IntoIter = IntoIter; + type IntoIter = IntoIter; /// Creates a consuming iterator, that is, one that moves each key-value /// pair out of the map in arbitrary order. The map cannot be used after @@ -1950,7 +2043,7 @@ impl IntoIterator for HashMap { /// let vec: Vec<(&str, i32)> = map.into_iter().collect(); /// ``` #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> IntoIter { IntoIter { inner: self.table.into_iter(), } @@ -2014,7 +2107,7 @@ where } } -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = (K, V); #[cfg_attr(feature = "inline-more", inline)] @@ -2026,15 +2119,15 @@ impl Iterator for IntoIter { self.inner.size_hint() } } -impl ExactSizeIterator for IntoIter { +impl ExactSizeIterator for IntoIter { #[cfg_attr(feature = "inline-more", inline)] fn len(&self) -> usize { self.inner.len() } } -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter {} -impl fmt::Debug for IntoIter { +impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } @@ -2110,7 +2203,7 @@ where } } -impl<'a, K, V> Iterator for Drain<'a, K, V> { +impl<'a, K, V, A: AllocRef + Clone> Iterator for Drain<'a, K, V, A> { type Item = (K, V); #[cfg_attr(feature = "inline-more", inline)] @@ -2122,25 +2215,26 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { self.inner.size_hint() } } -impl ExactSizeIterator for Drain<'_, K, V> { +impl ExactSizeIterator for Drain<'_, K, V, A> { #[cfg_attr(feature = "inline-more", inline)] fn len(&self) -> usize { self.inner.len() } } -impl FusedIterator for Drain<'_, K, V> {} +impl FusedIterator for Drain<'_, K, V, A> {} -impl fmt::Debug for Drain<'_, K, V> +impl fmt::Debug for Drain<'_, K, V, A> where K: fmt::Debug, V: fmt::Debug, + A: AllocRef + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } } -impl<'a, K, V, S> Entry<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> Entry<'a, K, V, S, A> { /// Sets the value of the entry, and returns an OccupiedEntry. /// /// # Examples @@ -2154,7 +2248,7 @@ impl<'a, K, V, S> Entry<'a, K, V, S> { /// assert_eq!(entry.key(), &"horseyland"); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S> + pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S, A> where K: Hash, S: BuildHasher, @@ -2276,7 +2370,7 @@ impl<'a, K, V, S> Entry<'a, K, V, S> { } } -impl<'a, K, V: Default, S> Entry<'a, K, V, S> { +impl<'a, K, V: Default, S, A: AllocRef + Clone> Entry<'a, K, V, S, A> { /// Ensures a value is in the entry by inserting the default value if empty, /// and returns a mutable reference to the value in the entry. /// @@ -2305,7 +2399,7 @@ impl<'a, K, V: Default, S> Entry<'a, K, V, S> { } } -impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> OccupiedEntry<'a, K, V, S, A> { /// Gets a reference to the key in the entry. /// /// # Examples @@ -2535,7 +2629,7 @@ impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> { } } -impl<'a, K, V, S> VacantEntry<'a, K, V, S> { +impl<'a, K, V, S, A: AllocRef + Clone> VacantEntry<'a, K, V, S, A> { /// Gets a reference to the key that would be used when inserting a value /// through the `VacantEntry`. /// @@ -2601,7 +2695,7 @@ impl<'a, K, V, S> VacantEntry<'a, K, V, S> { } #[cfg_attr(feature = "inline-more", inline)] - fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S> + fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S, A> where K: Hash, S: BuildHasher, @@ -2618,15 +2712,16 @@ impl<'a, K, V, S> VacantEntry<'a, K, V, S> { } } -impl FromIterator<(K, V)> for HashMap +impl FromIterator<(K, V)> for HashMap where K: Eq + Hash, S: BuildHasher + Default, + A: Default + AllocRef + Clone, { #[cfg_attr(feature = "inline-more", inline)] fn from_iter>(iter: T) -> Self { let iter = iter.into_iter(); - let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default()); + let mut map = Self::with_capacity_and_hasher_in(iter.size_hint().0, S::default(), A::default()); iter.for_each(|(k, v)| { map.insert(k, v); }); @@ -2634,10 +2729,11 @@ where } } -impl Extend<(K, V)> for HashMap +impl Extend<(K, V)> for HashMap where K: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { #[cfg_attr(feature = "inline-more", inline)] fn extend>(&mut self, iter: T) { @@ -2658,11 +2754,12 @@ where } } -impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap +impl<'a, K, V, S, A> Extend<(&'a K, &'a V)> for HashMap where K: Eq + Hash + Copy, V: Copy, S: BuildHasher, + A: AllocRef + Clone, { #[cfg_attr(feature = "inline-more", inline)] fn extend>(&mut self, iter: T) { @@ -2684,10 +2781,10 @@ fn assert_covariance() { fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> { v } - fn into_iter_key<'new>(v: IntoIter<&'static str, u8>) -> IntoIter<&'new str, u8> { + fn into_iter_key<'new, A: AllocRef + Clone>(v: IntoIter<&'static str, u8, A>) -> IntoIter<&'new str, u8, A> { v } - fn into_iter_val<'new>(v: IntoIter) -> IntoIter { + fn into_iter_val<'new, A: AllocRef + Clone>(v: IntoIter) -> IntoIter { v } fn keys_key<'a, 'new>(v: Keys<'a, &'static str, u8>) -> Keys<'a, &'new str, u8> { diff --git a/src/raw/alloc.rs b/src/raw/alloc.rs index d0291e713a..72401f9b7f 100644 --- a/src/raw/alloc.rs +++ b/src/raw/alloc.rs @@ -2,7 +2,7 @@ pub use self::inner::*; #[cfg(feature = "nightly")] mod inner { - pub use crate::alloc::alloc::{Alloc, Global}; + pub use crate::alloc::alloc::{AllocRef, Global}; } #[cfg(not(feature = "nightly"))] @@ -10,14 +10,14 @@ mod inner { use crate::alloc::alloc::{alloc, dealloc, Layout}; use core::ptr::NonNull; - pub trait Alloc { + pub trait AllocRef { unsafe fn alloc(&mut self, layout: Layout) -> Result, ()>; unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout); } #[derive(Copy, Clone)] pub struct Global; - impl Alloc for Global { + impl AllocRef for Global { unsafe fn alloc(&mut self, layout: Layout) -> Result, ()> { NonNull::new(alloc(layout)).ok_or(()) } @@ -25,4 +25,9 @@ mod inner { dealloc(ptr.as_ptr(), layout) } } + impl Default for Global { + fn default() -> Self { + Global + } + } } diff --git a/src/raw/mod.rs b/src/raw/mod.rs index ec9b8c1f6e..99411a0b68 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -32,7 +32,7 @@ cfg_if! { } mod alloc; -pub use self::alloc::{Alloc, Global}; +pub use self::alloc::{AllocRef, Global}; mod bitmask; @@ -331,7 +331,7 @@ impl Bucket { } /// A raw hash table with an unsafe API. -pub struct RawTable { +pub struct RawTable { // Mask to get an index from a hash value. The value is one less than the // number of buckets in the table. bucket_mask: usize, @@ -354,7 +354,7 @@ pub struct RawTable { alloc: A, } -impl RawTable { +impl RawTable { /// Creates a new empty hash table without allocating any memory. /// /// In effect this returns a table with exactly 1 bucket. However we can @@ -986,10 +986,10 @@ impl RawTable { } } -unsafe impl Send for RawTable where T: Send {} -unsafe impl Sync for RawTable where T: Sync {} +unsafe impl Send for RawTable where T: Send {} +unsafe impl Sync for RawTable where T: Sync {} -impl Clone for RawTable { +impl Clone for RawTable { fn clone(&self) -> Self { if self.is_empty_singleton() { Self::new(self.alloc.clone()) @@ -1046,7 +1046,7 @@ impl Clone for RawTable { } #[cfg(feature = "nightly")] -unsafe impl<#[may_dangle] T, A: Alloc + Clone> Drop for RawTable { +unsafe impl<#[may_dangle] T, A: AllocRef + Clone> Drop for RawTable { #[cfg_attr(feature = "inline-more", inline)] fn drop(&mut self) { if !self.is_empty_singleton() { @@ -1062,7 +1062,7 @@ unsafe impl<#[may_dangle] T, A: Alloc + Clone> Drop for RawTable { } } #[cfg(not(feature = "nightly"))] -impl Drop for RawTable { +impl Drop for RawTable { #[cfg_attr(feature = "inline-more", inline)] fn drop(&mut self) { if !self.is_empty_singleton() { @@ -1078,7 +1078,7 @@ impl Drop for RawTable { } } -impl IntoIterator for RawTable { +impl IntoIterator for RawTable { type Item = T; type IntoIter = RawIntoIter; @@ -1280,25 +1280,25 @@ impl ExactSizeIterator for RawIter {} impl FusedIterator for RawIter {} /// Iterator which consumes a table and returns elements. -pub struct RawIntoIter { +pub struct RawIntoIter { iter: RawIter, alloc: Option<(NonNull, Layout)>, marker: PhantomData, allocator: A, } -impl RawIntoIter { +impl RawIntoIter { #[cfg_attr(feature = "inline-more", inline)] pub fn iter(&self) -> RawIter { self.iter.clone() } } -unsafe impl Send for RawIntoIter where T: Send {} -unsafe impl Sync for RawIntoIter where T: Sync {} +unsafe impl Send for RawIntoIter where T: Send {} +unsafe impl Sync for RawIntoIter where T: Sync {} #[cfg(feature = "nightly")] -unsafe impl<#[may_dangle] T, A: Alloc + Clone> Drop for RawIntoIter { +unsafe impl<#[may_dangle] T, A: AllocRef + Clone> Drop for RawIntoIter { #[cfg_attr(feature = "inline-more", inline)] fn drop(&mut self) { unsafe { @@ -1317,7 +1317,7 @@ unsafe impl<#[may_dangle] T, A: Alloc + Clone> Drop for RawIntoIter { } } #[cfg(not(feature = "nightly"))] -impl Drop for RawIntoIter { +impl Drop for RawIntoIter { #[cfg_attr(feature = "inline-more", inline)] fn drop(&mut self) { unsafe { @@ -1337,7 +1337,7 @@ impl Drop for RawIntoIter { } } -impl Iterator for RawIntoIter { +impl Iterator for RawIntoIter { type Item = T; #[cfg_attr(feature = "inline-more", inline)] @@ -1351,11 +1351,11 @@ impl Iterator for RawIntoIter { } } -impl ExactSizeIterator for RawIntoIter {} -impl FusedIterator for RawIntoIter {} +impl ExactSizeIterator for RawIntoIter {} +impl FusedIterator for RawIntoIter {} /// Iterator which consumes elements without freeing the table storage. -pub struct RawDrain<'a, T, A: Alloc + Clone> { +pub struct RawDrain<'a, T, A: AllocRef + Clone> { iter: RawIter, // The table is moved into the iterator for the duration of the drain. This @@ -1369,17 +1369,17 @@ pub struct RawDrain<'a, T, A: Alloc + Clone> { marker: PhantomData<&'a RawTable>, } -impl RawDrain<'_, T, A> { +impl RawDrain<'_, T, A> { #[cfg_attr(feature = "inline-more", inline)] pub fn iter(&self) -> RawIter { self.iter.clone() } } -unsafe impl Send for RawDrain<'_, T, A> where T: Send {} -unsafe impl Sync for RawDrain<'_, T, A> where T: Sync {} +unsafe impl Send for RawDrain<'_, T, A> where T: Send {} +unsafe impl Sync for RawDrain<'_, T, A> where T: Sync {} -impl Drop for RawDrain<'_, T, A> { +impl Drop for RawDrain<'_, T, A> { #[cfg_attr(feature = "inline-more", inline)] fn drop(&mut self) { unsafe { @@ -1402,7 +1402,7 @@ impl Drop for RawDrain<'_, T, A> { } } -impl Iterator for RawDrain<'_, T, A> { +impl Iterator for RawDrain<'_, T, A> { type Item = T; #[cfg_attr(feature = "inline-more", inline)] @@ -1419,5 +1419,5 @@ impl Iterator for RawDrain<'_, T, A> { } } -impl ExactSizeIterator for RawDrain<'_, T, A> {} -impl FusedIterator for RawDrain<'_, T, A> {} +impl ExactSizeIterator for RawDrain<'_, T, A> {} +impl FusedIterator for RawDrain<'_, T, A> {} diff --git a/src/set.rs b/src/set.rs index 537a10d770..1f717303f8 100644 --- a/src/set.rs +++ b/src/set.rs @@ -5,6 +5,7 @@ use core::hash::{BuildHasher, Hash}; use core::iter::{Chain, FromIterator, FusedIterator}; use core::ops::{BitAnd, BitOr, BitXor, Sub}; +use crate::raw::{AllocRef, Global}; use super::map::{self, DefaultHashBuilder, HashMap, Keys}; // Future Optimization (FIXME!) @@ -112,8 +113,8 @@ use super::map::{self, DefaultHashBuilder, HashMap, Keys}; /// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html /// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html #[derive(Clone)] -pub struct HashSet { - pub(crate) map: HashMap, +pub struct HashSet { + pub(crate) map: HashMap, } #[cfg(feature = "ahash")] @@ -156,7 +157,47 @@ impl HashSet { } } -impl HashSet { +#[cfg(feature = "ahash")] +impl HashSet { + /// Creates an empty `HashSet`. + /// + /// The hash set is initially created with a capacity of 0, so it will not allocate until it + /// is first inserted into. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashSet; + /// let set: HashSet = HashSet::new(); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn new_in(alloc: A) -> Self { + Self { + map: HashMap::new_in(alloc), + } + } + + /// Creates an empty `HashSet` with the specified capacity. + /// + /// The hash set will be able to hold at least `capacity` elements without + /// reallocating. If `capacity` is 0, the hash set will not allocate. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashSet; + /// let set: HashSet = HashSet::with_capacity(10); + /// assert!(set.capacity() >= 10); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Self { + map: HashMap::with_capacity_in(capacity, alloc), + } + } +} + +impl HashSet { /// Returns the number of elements the set can hold without reallocating. /// /// # Examples @@ -246,7 +287,7 @@ impl HashSet { /// assert!(set.is_empty()); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn drain(&mut self) -> Drain<'_, T> { + pub fn drain(&mut self) -> Drain<'_, T, A> { Drain { iter: self.map.drain(), } @@ -329,6 +370,68 @@ where map: HashMap::with_capacity_and_hasher(capacity, hasher), } } +} + +impl HashSet +where + T: Eq + Hash, + S: BuildHasher, + A: AllocRef + Clone, +{ + /// Creates a new empty hash set which will use the given hasher to hash + /// keys. + /// + /// The hash set is also created with the default initial capacity. + /// + /// Warning: `hasher` is normally randomly generated, and + /// is designed to allow `HashSet`s to be resistant to attacks that + /// cause many collisions and very poor performance. Setting it + /// manually using this function can expose a DoS attack vector. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashSet; + /// use hashbrown::hash_map::DefaultHashBuilder; + /// + /// let s = DefaultHashBuilder::default(); + /// let mut set = HashSet::with_hasher(s); + /// set.insert(2); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn with_hasher_in(hasher: S, alloc: A) -> Self { + Self { + map: HashMap::with_hasher_in(hasher, alloc), + } + } + + /// Creates an empty `HashSet` with the specified capacity, using + /// `hasher` to hash the keys. + /// + /// The hash set will be able to hold at least `capacity` elements without + /// reallocating. If `capacity` is 0, the hash set will not allocate. + /// + /// Warning: `hasher` is normally randomly generated, and + /// is designed to allow `HashSet`s to be resistant to attacks that + /// cause many collisions and very poor performance. Setting it + /// manually using this function can expose a DoS attack vector. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashSet; + /// use hashbrown::hash_map::DefaultHashBuilder; + /// + /// let s = DefaultHashBuilder::default(); + /// let mut set = HashSet::with_capacity_and_hasher(10, s); + /// set.insert(1); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn with_capacity_and_hasher_in(capacity: usize, hasher: S, alloc: A) -> Self { + Self { + map: HashMap::with_capacity_and_hasher_in(capacity, hasher, alloc), + } + } /// Returns a reference to the set's [`BuildHasher`]. /// @@ -462,7 +565,7 @@ where /// assert_eq!(diff, [4].iter().collect()); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S> { + pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S, A> { Difference { iter: self.iter(), other, @@ -491,7 +594,7 @@ where /// assert_eq!(diff1, [1, 4].iter().collect()); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S> { + pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S, A> { SymmetricDifference { iter: self.difference(other).chain(other.difference(self)), } @@ -516,7 +619,7 @@ where /// assert_eq!(intersection, [2, 3].iter().collect()); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S> { + pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S, A> { let (smaller, larger) = if self.len() <= other.len() { (self, other) } else { @@ -547,7 +650,7 @@ where /// assert_eq!(union, [1, 2, 3, 4].iter().collect()); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, S> { + pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, S, A> { let (smaller, larger) = if self.len() <= other.len() { (self, other) } else { @@ -865,10 +968,11 @@ where } } -impl PartialEq for HashSet +impl PartialEq for HashSet where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { fn eq(&self, other: &Self) -> bool { if self.len() != other.len() { @@ -879,40 +983,44 @@ where } } -impl Eq for HashSet +impl Eq for HashSet where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { } -impl fmt::Debug for HashSet +impl fmt::Debug for HashSet where T: Eq + Hash + fmt::Debug, S: BuildHasher, + A: AllocRef + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_set().entries(self.iter()).finish() } } -impl FromIterator for HashSet +impl FromIterator for HashSet where T: Eq + Hash, S: BuildHasher + Default, + A: Default + AllocRef + Clone, { #[cfg_attr(feature = "inline-more", inline)] fn from_iter>(iter: I) -> Self { - let mut set = Self::with_hasher(Default::default()); + let mut set = Self::with_hasher_in(Default::default(), Default::default()); set.extend(iter); set } } -impl Extend for HashSet +impl Extend for HashSet where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { #[cfg_attr(feature = "inline-more", inline)] fn extend>(&mut self, iter: I) { @@ -920,10 +1028,11 @@ where } } -impl<'a, T, S> Extend<&'a T> for HashSet +impl<'a, T, S, A> Extend<&'a T> for HashSet where T: 'a + Eq + Hash + Copy, S: BuildHasher, + A: AllocRef + Clone, { #[cfg_attr(feature = "inline-more", inline)] fn extend>(&mut self, iter: I) { @@ -931,10 +1040,11 @@ where } } -impl Default for HashSet +impl Default for HashSet where T: Eq + Hash, S: BuildHasher + Default, + A: Default + AllocRef + Clone, { /// Creates an empty `HashSet` with the `Default` value for the hasher. #[cfg_attr(feature = "inline-more", inline)] @@ -945,10 +1055,11 @@ where } } -impl BitOr<&HashSet> for &HashSet +impl BitOr<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default, + A: AllocRef + Clone, { type Output = HashSet; @@ -972,15 +1083,16 @@ where /// } /// assert_eq!(i, expected.len()); /// ``` - fn bitor(self, rhs: &HashSet) -> HashSet { + fn bitor(self, rhs: &HashSet) -> HashSet { self.union(rhs).cloned().collect() } } -impl BitAnd<&HashSet> for &HashSet +impl BitAnd<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default, + A: AllocRef + Clone, { type Output = HashSet; @@ -1004,7 +1116,7 @@ where /// } /// assert_eq!(i, expected.len()); /// ``` - fn bitand(self, rhs: &HashSet) -> HashSet { + fn bitand(self, rhs: &HashSet) -> HashSet { self.intersection(rhs).cloned().collect() } } @@ -1091,8 +1203,8 @@ pub struct Iter<'a, K> { /// /// [`HashSet`]: struct.HashSet.html /// [`into_iter`]: struct.HashSet.html#method.into_iter -pub struct IntoIter { - iter: map::IntoIter, +pub struct IntoIter { + iter: map::IntoIter, } /// A draining iterator over the items of a `HashSet`. @@ -1102,8 +1214,8 @@ pub struct IntoIter { /// /// [`HashSet`]: struct.HashSet.html /// [`drain`]: struct.HashSet.html#method.drain -pub struct Drain<'a, K> { - iter: map::Drain<'a, K, ()>, +pub struct Drain<'a, K, A: AllocRef + Clone> { + iter: map::Drain<'a, K, (), A>, } /// A lazy iterator producing elements in the intersection of `HashSet`s. @@ -1113,11 +1225,11 @@ pub struct Drain<'a, K> { /// /// [`HashSet`]: struct.HashSet.html /// [`intersection`]: struct.HashSet.html#method.intersection -pub struct Intersection<'a, T, S> { +pub struct Intersection<'a, T, S, A: AllocRef + Clone> { // iterator of the first set iter: Iter<'a, T>, // the second set - other: &'a HashSet, + other: &'a HashSet, } /// A lazy iterator producing elements in the difference of `HashSet`s. @@ -1127,11 +1239,11 @@ pub struct Intersection<'a, T, S> { /// /// [`HashSet`]: struct.HashSet.html /// [`difference`]: struct.HashSet.html#method.difference -pub struct Difference<'a, T, S> { +pub struct Difference<'a, T, S, A: AllocRef + Clone> { // iterator of the first set iter: Iter<'a, T>, // the second set - other: &'a HashSet, + other: &'a HashSet, } /// A lazy iterator producing elements in the symmetric difference of `HashSet`s. @@ -1141,8 +1253,8 @@ pub struct Difference<'a, T, S> { /// /// [`HashSet`]: struct.HashSet.html /// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference -pub struct SymmetricDifference<'a, T, S> { - iter: Chain, Difference<'a, T, S>>, +pub struct SymmetricDifference<'a, T, S, A: AllocRef + Clone> { + iter: Chain, Difference<'a, T, S, A>>, } /// A lazy iterator producing elements in the union of `HashSet`s. @@ -1152,11 +1264,11 @@ pub struct SymmetricDifference<'a, T, S> { /// /// [`HashSet`]: struct.HashSet.html /// [`union`]: struct.HashSet.html#method.union -pub struct Union<'a, T, S> { - iter: Chain, Difference<'a, T, S>>, +pub struct Union<'a, T, S, A: AllocRef + Clone> { + iter: Chain, Difference<'a, T, S, A>>, } -impl<'a, T, S> IntoIterator for &'a HashSet { +impl<'a, T, S, A: AllocRef + Clone> IntoIterator for &'a HashSet { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1166,9 +1278,9 @@ impl<'a, T, S> IntoIterator for &'a HashSet { } } -impl IntoIterator for HashSet { +impl IntoIterator for HashSet { type Item = T; - type IntoIter = IntoIter; + type IntoIter = IntoIter; /// Creates a consuming iterator, that is, one that moves each value out /// of the set in arbitrary order. The set cannot be used after calling @@ -1191,7 +1303,7 @@ impl IntoIterator for HashSet { /// } /// ``` #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> IntoIter { IntoIter { iter: self.map.into_iter(), } @@ -1232,7 +1344,7 @@ impl fmt::Debug for Iter<'_, K> { } } -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = K; #[cfg_attr(feature = "inline-more", inline)] @@ -1244,22 +1356,22 @@ impl Iterator for IntoIter { self.iter.size_hint() } } -impl ExactSizeIterator for IntoIter { +impl ExactSizeIterator for IntoIter { #[cfg_attr(feature = "inline-more", inline)] fn len(&self) -> usize { self.iter.len() } } -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter {} -impl fmt::Debug for IntoIter { +impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let entries_iter = self.iter.iter().map(|(k, _)| k); f.debug_list().entries(entries_iter).finish() } } -impl Iterator for Drain<'_, K> { +impl Iterator for Drain<'_, K, A> { type Item = K; #[cfg_attr(feature = "inline-more", inline)] @@ -1271,22 +1383,22 @@ impl Iterator for Drain<'_, K> { self.iter.size_hint() } } -impl ExactSizeIterator for Drain<'_, K> { +impl ExactSizeIterator for Drain<'_, K, A> { #[cfg_attr(feature = "inline-more", inline)] fn len(&self) -> usize { self.iter.len() } } -impl FusedIterator for Drain<'_, K> {} +impl FusedIterator for Drain<'_, K, A> {} -impl fmt::Debug for Drain<'_, K> { +impl fmt::Debug for Drain<'_, K, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let entries_iter = self.iter.iter().map(|(k, _)| k); f.debug_list().entries(entries_iter).finish() } } -impl Clone for Intersection<'_, T, S> { +impl Clone for Intersection<'_, T, S, A> { #[cfg_attr(feature = "inline-more", inline)] fn clone(&self) -> Self { Intersection { @@ -1296,10 +1408,11 @@ impl Clone for Intersection<'_, T, S> { } } -impl<'a, T, S> Iterator for Intersection<'a, T, S> +impl<'a, T, S, A> Iterator for Intersection<'a, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { type Item = &'a T; @@ -1320,24 +1433,26 @@ where } } -impl fmt::Debug for Intersection<'_, T, S> +impl fmt::Debug for Intersection<'_, T, S, A> where T: fmt::Debug + Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } -impl FusedIterator for Intersection<'_, T, S> +impl FusedIterator for Intersection<'_, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { } -impl Clone for Difference<'_, T, S> { +impl Clone for Difference<'_, T, S, A> { #[cfg_attr(feature = "inline-more", inline)] fn clone(&self) -> Self { Difference { @@ -1347,10 +1462,11 @@ impl Clone for Difference<'_, T, S> { } } -impl<'a, T, S> Iterator for Difference<'a, T, S> +impl<'a, T, S, A> Iterator for Difference<'a, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { type Item = &'a T; @@ -1371,24 +1487,26 @@ where } } -impl FusedIterator for Difference<'_, T, S> +impl FusedIterator for Difference<'_, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { } -impl fmt::Debug for Difference<'_, T, S> +impl fmt::Debug for Difference<'_, T, S, A> where T: fmt::Debug + Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } -impl Clone for SymmetricDifference<'_, T, S> { +impl Clone for SymmetricDifference<'_, T, S, A> { #[cfg_attr(feature = "inline-more", inline)] fn clone(&self) -> Self { SymmetricDifference { @@ -1397,10 +1515,11 @@ impl Clone for SymmetricDifference<'_, T, S> { } } -impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> +impl<'a, T, S, A> Iterator for SymmetricDifference<'a, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { type Item = &'a T; @@ -1414,24 +1533,26 @@ where } } -impl FusedIterator for SymmetricDifference<'_, T, S> +impl FusedIterator for SymmetricDifference<'_, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { } -impl fmt::Debug for SymmetricDifference<'_, T, S> +impl fmt::Debug for SymmetricDifference<'_, T, S, A> where T: fmt::Debug + Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } -impl Clone for Union<'_, T, S> { +impl Clone for Union<'_, T, S, A> { #[cfg_attr(feature = "inline-more", inline)] fn clone(&self) -> Self { Union { @@ -1440,27 +1561,30 @@ impl Clone for Union<'_, T, S> { } } -impl FusedIterator for Union<'_, T, S> +impl FusedIterator for Union<'_, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { } -impl fmt::Debug for Union<'_, T, S> +impl fmt::Debug for Union<'_, T, S, A> where T: fmt::Debug + Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } -impl<'a, T, S> Iterator for Union<'a, T, S> +impl<'a, T, S, A> Iterator for Union<'a, T, S, A> where T: Eq + Hash, S: BuildHasher, + A: AllocRef + Clone, { type Item = &'a T; @@ -1482,30 +1606,30 @@ fn assert_covariance() { fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { v } - fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { + fn into_iter<'new, A: AllocRef + Clone>(v: IntoIter<&'static str, A>) -> IntoIter<&'new str, A> { v } - fn difference<'a, 'new>( - v: Difference<'a, &'static str, DefaultHashBuilder>, - ) -> Difference<'a, &'new str, DefaultHashBuilder> { + fn difference<'a, 'new, A: AllocRef + Clone>( + v: Difference<'a, &'static str, DefaultHashBuilder, A>, + ) -> Difference<'a, &'new str, DefaultHashBuilder, A> { v } - fn symmetric_difference<'a, 'new>( - v: SymmetricDifference<'a, &'static str, DefaultHashBuilder>, - ) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder> { + fn symmetric_difference<'a, 'new, A: AllocRef + Clone>( + v: SymmetricDifference<'a, &'static str, DefaultHashBuilder, A>, + ) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder, A> { v } - fn intersection<'a, 'new>( - v: Intersection<'a, &'static str, DefaultHashBuilder>, - ) -> Intersection<'a, &'new str, DefaultHashBuilder> { + fn intersection<'a, 'new, A: AllocRef + Clone>( + v: Intersection<'a, &'static str, DefaultHashBuilder, A>, + ) -> Intersection<'a, &'new str, DefaultHashBuilder, A> { v } - fn union<'a, 'new>( - v: Union<'a, &'static str, DefaultHashBuilder>, - ) -> Union<'a, &'new str, DefaultHashBuilder> { + fn union<'a, 'new, A: AllocRef + Clone>( + v: Union<'a, &'static str, DefaultHashBuilder, A>, + ) -> Union<'a, &'new str, DefaultHashBuilder, A> { v } - fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { + fn drain<'new, A: AllocRef + Clone>(d: Drain<'static, &'static str, A>) -> Drain<'new, &'new str, A> { d } }