diff --git a/.travis.yml b/.travis.yml index 4d74980..625ee3e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ sudo: false matrix: fast_finish: true include: - - rust: 1.28.0 + - rust: 1.31.0 - rust: stable - rust: beta - rust: nightly diff --git a/Cargo.toml b/Cargo.toml index ebd564a..321fa4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,15 @@ [package] authors = ["Josh Stone "] name = "rayon-hash" -version = "0.4.1" +version = "0.5.0" repository = "https://github.com/rayon-rs/rayon-hash" documentation = "https://docs.rs/rayon-hash/" keywords = ["parallel", "iterator", "hash", "map", "set"] categories = ["concurrency", "data-structures"] -description = "HashMap and HashSet with support for Rayon parallel iterators" +description = "(deprecated) HashMap and HashSet with support for Rayon parallel iterators" license = "Apache-2.0/MIT" readme = "README.md" +edition = "2018" [dependencies] rayon = "1.0" @@ -16,3 +17,10 @@ rayon = "1.0" [dev-dependencies] rand = "0.6" rand_xorshift = "0.1" + +[dev-dependencies.hashbrown] +version = "0.3.0" +features = ["rayon"] + +[badges] +maintenance = { status = "deprecated" } diff --git a/README.md b/README.md index 366e9df..0ffc4e6 100644 --- a/README.md +++ b/README.md @@ -3,23 +3,35 @@ [![rayon-hash crate](https://img.shields.io/crates/v/rayon-hash.svg)](https://crates.io/crates/rayon-hash) [![rayon-hash documentation](https://docs.rs/rayon-hash/badge.svg)](https://docs.rs/rayon-hash) [![Travis Status](https://travis-ci.org/rayon-rs/rayon-hash.svg?branch=master)](https://travis-ci.org/rayon-rs/rayon-hash) +![deprecated](https://img.shields.io/badge/maintenance-deprecated-red.svg) -The `rayon-hash` crate duplicates the standard `HashMap` and `HashSet`, adding -native support for Rayon parallel iterators. +This crate is now **deprecated**, because the [new implementation in `std`] +also exists as the [`hashbrown`] crate with its own "rayon" feature. + +[new implementation in `std`]: https://github.com/rust-lang/rust/pull/58623 +[`hashbrown`]: https://crates.io/crates/hashbrown + +The `rayon-hash` crate duplicates the _former_ standard `HashMap` and +`HashSet`, adding native support for Rayon parallel iterators. Rayon does provide iterators for these standard types already, but since it can't access internal fields, it has to collect to an intermediate vector to be split into parallel jobs. With the custom types in `rayon-hash`, we can instead read the raw hash table directly, for much better performance. +Benchmarks using `rustc 1.36.0-nightly (e938c2b9a 2019-04-23)`, before the +`hashbrown` implementation had merged into `std`: + ```text -test rayon_set_sum_parallel ... bench: 1,035,111 ns/iter (+/- 57,327) -test rayon_set_sum_serial ... bench: 7,500,179 ns/iter (+/- 96,918) -test std_set_sum_parallel ... bench: 6,799,231 ns/iter (+/- 94,154) -test std_set_sum_serial ... bench: 7,634,174 ns/iter (+/- 84,806) +test hashbrown_set_sum_parallel ... bench: 617,405 ns/iter (+/- 58,565) +test hashbrown_set_sum_serial ... bench: 2,655,882 ns/iter (+/- 15,104) +test rayon_hash_set_sum_parallel ... bench: 1,368,058 ns/iter (+/- 75,984) +test rayon_hash_set_sum_serial ... bench: 7,558,175 ns/iter (+/- 190,545) +test std_hash_set_sum_parallel ... bench: 6,869,490 ns/iter (+/- 47,897) +test std_hash_set_sum_serial ... bench: 7,591,704 ns/iter (+/- 154,438) ``` -This crate currently requires `rustc 1.28.0` or greater. +This crate currently requires `rustc 1.31.0` or greater. ## Known limitations diff --git a/benches/set_sum.rs b/benches/set_sum.rs index 1fb47a5..0187438 100644 --- a/benches/set_sum.rs +++ b/benches/set_sum.rs @@ -6,12 +6,14 @@ extern crate rayon; extern crate rayon_hash; extern crate test; +use hashbrown::HashSet as HashBrownSet; use rand::distributions::Standard; use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; use rayon::prelude::*; use rayon_hash::HashSet as RayonHashSet; use std::collections::HashSet as StdHashSet; +use std::collections::hash_map::RandomState; use std::iter::FromIterator; use test::Bencher; @@ -39,7 +41,9 @@ macro_rules! bench_set_sum { }; } -bench_set_sum!{std_set_sum_serial, StdHashSet<_>, iter} -bench_set_sum!{std_set_sum_parallel, StdHashSet<_>, par_iter} -bench_set_sum!{rayon_set_sum_serial, RayonHashSet<_>, iter} -bench_set_sum!{rayon_set_sum_parallel, RayonHashSet<_>, par_iter} +bench_set_sum!{std_hash_set_sum_serial, StdHashSet<_, RandomState>, iter} +bench_set_sum!{std_hash_set_sum_parallel, StdHashSet<_, RandomState>, par_iter} +bench_set_sum!{rayon_hash_set_sum_serial, RayonHashSet<_, RandomState>, iter} +bench_set_sum!{rayon_hash_set_sum_parallel, RayonHashSet<_, RandomState>, par_iter} +bench_set_sum!{hashbrown_set_sum_serial, HashBrownSet<_, RandomState>, iter} +bench_set_sum!{hashbrown_set_sum_parallel, HashBrownSet<_, RandomState>, par_iter} diff --git a/src/intrinsics.rs b/src/intrinsics.rs new file mode 100644 index 0000000..5f1926b --- /dev/null +++ b/src/intrinsics.rs @@ -0,0 +1,4 @@ +#[inline(always)] +pub unsafe fn unlikely(b: bool) -> bool { + b +} diff --git a/src/lib.rs b/src/lib.rs index a9d2c09..f0afdd4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,8 @@ extern crate rayon; #[cfg(test)] extern crate rand; mod alloc; +#[cfg(rayon_hash_unstable)] +mod intrinsics; mod ptr; // #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/par/map.rs b/src/par/map.rs index 0b7d6f4..4cb5afd 100644 --- a/src/par/map.rs +++ b/src/par/map.rs @@ -3,7 +3,7 @@ use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, Pa use std::hash::{BuildHasher, Hash}; use super::table; -use HashMap; +use crate::HashMap; pub use self::table::{ParIntoIter, ParIter, ParIterMut}; pub use self::table::{ParKeys, ParValues, ParValuesMut}; diff --git a/src/par/set.rs b/src/par/set.rs index 692489f..391bee8 100644 --- a/src/par/set.rs +++ b/src/par/set.rs @@ -4,7 +4,7 @@ use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, Pa use std::hash::{BuildHasher, Hash}; use super::map; -use HashSet; +use crate::HashSet; pub struct ParIntoIter { inner: map::ParIntoIter, diff --git a/src/par/table.rs b/src/par/table.rs index 6421ea2..8543578 100644 --- a/src/par/table.rs +++ b/src/par/table.rs @@ -5,7 +5,7 @@ use std::ptr; use rayon::iter::plumbing::*; use rayon::prelude::*; -use std_hash::table::{RawBucket, RawTable}; +use crate::std_hash::table::{RawBucket, RawTable}; struct SplitBuckets<'a, K, V> { bucket: RawBucket, diff --git a/src/std_hash/map.rs b/src/std_hash/map.rs index 486a8fc..b341ef2 100644 --- a/src/std_hash/map.rs +++ b/src/std_hash/map.rs @@ -1,17 +1,9 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use self::Entry::*; use self::VacantEntryState::*; -use alloc::CollectionAllocErr; +use crate::alloc::CollectionAllocErr; +#[cfg(rayon_hash_unstable)] +use crate::intrinsics::unlikely; use std::borrow::Borrow; use std::cmp::max; use std::fmt::{self, Debug}; @@ -31,7 +23,7 @@ use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucke use super::table::BucketState::{Empty, Full}; use super::table::Fallibility::{Fallible, Infallible}; -const MIN_NONZERO_RAW_CAPACITY: usize = 32; // must be a power of two +const MIN_NONZERO_RAW_CAPACITY: usize = 32; // must be a power of two /// The default behavior of HashMap implements a maximum load factor of 90.9%. #[derive(Clone)] @@ -321,6 +313,9 @@ const DISPLACEMENT_THRESHOLD: usize = 128; /// } /// } /// +/// // Look up the value for a key (will panic if the key is not found). +/// println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]); +/// /// // Iterate over everything. /// for (book, review) in &book_reviews { /// println!("{}: \"{}\"", book, review); @@ -356,7 +351,7 @@ const DISPLACEMENT_THRESHOLD: usize = 128; /// *stat += random_stat_buff(); /// ``` /// -/// The easiest way to use `HashMap` with a custom type as key is to derive [`Eq`] and [`Hash`]. +/// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`]. /// We must also derive [`PartialEq`]. /// /// [`Eq`]: ../../std/cmp/trait.Eq.html @@ -379,7 +374,7 @@ const DISPLACEMENT_THRESHOLD: usize = 128; /// } /// /// impl Viking { -/// /// Create a new Viking. +/// /// Creates a new Viking. /// fn new(name: &str, country: &str) -> Viking { /// Viking { name: name.to_string(), country: country.to_string() } /// } @@ -544,7 +539,7 @@ fn search_hashed_nonempty_mut(table: M, hash: SafeHash, mut is_match } } -fn pop_internal(starting_bucket: FullBucketMut) +fn pop_internal(starting_bucket: FullBucketMut<'_, K, V>) -> (K, V, &mut RawTable) { let (empty, retkey, retval) = starting_bucket.take(); @@ -566,7 +561,7 @@ fn pop_internal(starting_bucket: FullBucketMut) (retkey, retval, gap.into_table()) } -/// Perform robin hood bucket stealing at the given `bucket`. You must +/// Performs robin hood bucket stealing at the given `bucket`. You must /// also pass that bucket's displacement so we don't have to recalculate it. /// /// `hash`, `key`, and `val` are the elements to "robin hood" into the hashtable. @@ -726,6 +721,232 @@ impl HashMap { } } +impl HashMap { + /// Returns the number of elements the map can hold without reallocating. + /// + /// This number is a lower bound; the `HashMap` might be able to hold + /// more, but is guaranteed to be able to hold at least this many. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// let map: HashMap = HashMap::with_capacity(100); + /// assert!(map.capacity() >= 100); + /// ``` + #[inline] + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.resize_policy.capacity(self.raw_capacity()) + } + + /// Returns the hash map's raw capacity. + #[inline] + fn raw_capacity(&self) -> usize { + self.table.capacity() + } + + /// An iterator visiting all keys in arbitrary order. + /// The iterator element type is `&'a K`. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// for key in map.keys() { + /// println!("{}", key); + /// } + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn keys(&self) -> Keys<'_, K, V> { + Keys { inner: self.iter() } + } + + /// An iterator visiting all values in arbitrary order. + /// The iterator element type is `&'a V`. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// for val in map.values() { + /// println!("{}", val); + /// } + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn values(&self) -> Values<'_, K, V> { + Values { inner: self.iter() } + } + + /// An iterator visiting all values mutably in arbitrary order. + /// The iterator element type is `&'a mut V`. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut map = HashMap::new(); + /// + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// for val in map.values_mut() { + /// *val = *val + 10; + /// } + /// + /// for val in map.values() { + /// println!("{}", val); + /// } + /// ``` + // #[stable(feature = "map_values_mut", since = "1.10.0")] + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + ValuesMut { inner: self.iter_mut() } + } + + /// An iterator visiting all key-value pairs in arbitrary order. + /// The iterator element type is `(&'a K, &'a V)`. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// for (key, val) in map.iter() { + /// println!("key: {} val: {}", key, val); + /// } + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, K, V> { + Iter { inner: self.table.iter() } + } + + /// An iterator visiting all key-value pairs in arbitrary order, + /// with mutable references to the values. + /// The iterator element type is `(&'a K, &'a mut V)`. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// // Update all values + /// for (_, val) in map.iter_mut() { + /// *val *= 2; + /// } + /// + /// for (key, val) in &map { + /// println!("key: {} val: {}", key, val); + /// } + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + IterMut { inner: self.table.iter_mut() } + } + + /// Returns the number of elements in the map. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut a = HashMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.table.size() + } + + /// Returns `true` if the map contains no elements. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut a = HashMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1, "a"); + /// assert!(!a.is_empty()); + /// ``` + #[inline] + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Clears the map, returning all key-value pairs as an iterator. Keeps the + /// allocated memory for reuse. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut a = HashMap::new(); + /// a.insert(1, "a"); + /// a.insert(2, "b"); + /// + /// for (k, v) in a.drain().take(1) { + /// assert!(k == 1 || k == 2); + /// assert!(v == "a" || v == "b"); + /// } + /// + /// assert!(a.is_empty()); + /// ``` + #[inline] + // #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self) -> Drain<'_, K, V> { + Drain { inner: self.table.drain() } + } + + /// Clears the map, removing all key-value pairs. Keeps the allocated memory + /// for reuse. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashMap; + /// + /// let mut a = HashMap::new(); + /// a.insert(1, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn clear(&mut self) { + self.drain(); + } +} + impl HashMap where K: Eq + Hash, S: BuildHasher @@ -812,30 +1033,6 @@ impl HashMap &self.hash_builder } - /// Returns the number of elements the map can hold without reallocating. - /// - /// This number is a lower bound; the `HashMap` might be able to hold - /// more, but is guaranteed to be able to hold at least this many. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// let map: HashMap = HashMap::with_capacity(100); - /// assert!(map.capacity() >= 100); - /// ``` - #[inline] - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn capacity(&self) -> usize { - self.resize_policy.capacity(self.raw_capacity()) - } - - /// Returns the hash map's raw capacity. - #[inline] - fn raw_capacity(&self) -> usize { - self.table.capacity() - } - /// Reserves capacity for at least `additional` more elements to be inserted /// in the `HashMap`. The collection may reserve more space to avoid /// frequent reallocations. @@ -853,6 +1050,7 @@ impl HashMap /// let mut map: HashMap<&str, i32> = HashMap::new(); /// map.reserve(10); /// ``` + #[inline] // #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { match self.reserve_internal(additional, Infallible) { @@ -883,6 +1081,7 @@ impl HashMap self.reserve_internal(additional, Fallible) } + #[inline] fn reserve_internal(&mut self, additional: usize, fallibility: Fallibility) -> Result<(), CollectionAllocErr> { @@ -1018,7 +1217,7 @@ impl HashMap /// map.shrink_to(0); /// assert!(map.capacity() >= 2); /// ``` - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + #[cfg(rayon_hash_unstable)] // #[unstable(feature = "shrink_to", reason = "new API", issue="56431")] pub fn shrink_to(&mut self, min_capacity: usize) { assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); @@ -1054,127 +1253,6 @@ impl HashMap } } - /// An iterator visiting all keys in arbitrary order. - /// The iterator element type is `&'a K`. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for key in map.keys() { - /// println!("{}", key); - /// } - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn keys(&self) -> Keys { - Keys { inner: self.iter() } - } - - /// An iterator visiting all values in arbitrary order. - /// The iterator element type is `&'a V`. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for val in map.values() { - /// println!("{}", val); - /// } - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn values(&self) -> Values { - Values { inner: self.iter() } - } - - /// An iterator visiting all values mutably in arbitrary order. - /// The iterator element type is `&'a mut V`. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut map = HashMap::new(); - /// - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for val in map.values_mut() { - /// *val = *val + 10; - /// } - /// - /// for val in map.values() { - /// println!("{}", val); - /// } - /// ``` - // #[stable(feature = "map_values_mut", since = "1.10.0")] - pub fn values_mut(&mut self) -> ValuesMut { - ValuesMut { inner: self.iter_mut() } - } - - /// An iterator visiting all key-value pairs in arbitrary order. - /// The iterator element type is `(&'a K, &'a V)`. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for (key, val) in map.iter() { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter { - Iter { inner: self.table.iter() } - } - - /// An iterator visiting all key-value pairs in arbitrary order, - /// with mutable references to the values. - /// The iterator element type is `(&'a K, &'a mut V)`. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Update all values - /// for (_, val) in map.iter_mut() { - /// *val *= 2; - /// } - /// - /// for (key, val) in &map { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter_mut(&mut self) -> IterMut { - IterMut { inner: self.table.iter_mut() } - } - /// Gets the given key's corresponding entry in the map for in-place manipulation. /// /// # Examples @@ -1195,7 +1273,7 @@ impl HashMap /// assert_eq!(letters.get(&'y'), None); /// ``` // #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: K) -> Entry { + pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { // Gotta resize now. self.reserve(1); let hash = self.make_hash(&key); @@ -1203,85 +1281,6 @@ impl HashMap .into_entry(key).expect("unreachable") } - /// Returns the number of elements in the map. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn len(&self) -> usize { - self.table.size() - } - - /// Returns true if the map contains no elements. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1, "a"); - /// assert!(!a.is_empty()); - /// ``` - #[inline] - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Clears the map, returning all key-value pairs as an iterator. Keeps the - /// allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// - /// for (k, v) in a.drain().take(1) { - /// assert!(k == 1 || k == 2); - /// assert!(v == "a" || v == "b"); - /// } - /// - /// assert!(a.is_empty()); - /// ``` - #[inline] - // #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self) -> Drain { - Drain { inner: self.table.drain() } - } - - /// Clears the map, removing all key-value pairs. Keeps the allocated memory - /// for reuse. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.clear(); - /// assert!(a.is_empty()); - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn clear(&mut self) { - self.drain(); - } - /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but @@ -1337,7 +1336,7 @@ impl HashMap self.search(k).map(|bucket| bucket.into_refs()) } - /// Returns true if the map contains a value for the specified key. + /// Returns `true` if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for @@ -1570,10 +1569,11 @@ impl HashMap /// where the key should go, meaning the keys may become "lost" if their /// location does not reflect their state. For instance, if you change a key /// so that the map now contains keys which compare equal, search may start - /// acting eratically, with two keys randomly masking eachother. Implementations + /// 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(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] - pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut { + #[inline(always)] + #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] + pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { self.reserve(1); RawEntryBuilderMut { map: self } } @@ -1593,8 +1593,8 @@ impl HashMap /// `get` should be preferred. /// /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] - pub fn raw_entry(&self) -> RawEntryBuilder { + #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] + pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { RawEntryBuilder { map: self } } } @@ -1628,7 +1628,7 @@ impl Debug for HashMap V: Debug, S: BuildHasher { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.iter()).finish() } } @@ -1645,7 +1645,7 @@ impl Default for HashMap } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap +impl Index<&Q> for HashMap where K: Eq + Hash + Borrow, Q: Eq + Hash, S: BuildHasher @@ -1677,15 +1677,15 @@ pub struct Iter<'a, K: 'a, V: 'a> { // FIXME(#26925) Remove in favor of `#[derive(Clone)]` // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Clone for Iter<'a, K, V> { - fn clone(&self) -> Iter<'a, K, V> { +impl Clone for Iter<'_, K, V> { + fn clone(&self) -> Self { Iter { inner: self.inner.clone() } } } // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl fmt::Debug for Iter<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries(self.clone()) .finish() @@ -1730,15 +1730,15 @@ pub struct Keys<'a, K: 'a, V: 'a> { // FIXME(#26925) Remove in favor of `#[derive(Clone)]` // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Clone for Keys<'a, K, V> { - fn clone(&self) -> Keys<'a, K, V> { +impl Clone for Keys<'_, K, V> { + fn clone(&self) -> Self { Keys { inner: self.inner.clone() } } } // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K: Debug, V> fmt::Debug for Keys<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl fmt::Debug for Keys<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries(self.clone()) .finish() @@ -1759,15 +1759,15 @@ pub struct Values<'a, K: 'a, V: 'a> { // FIXME(#26925) Remove in favor of `#[derive(Clone)]` // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Clone for Values<'a, K, V> { - fn clone(&self) -> Values<'a, K, V> { +impl Clone for Values<'_, K, V> { + fn clone(&self) -> Self { Values { inner: self.inner.clone() } } } // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K, V: Debug> fmt::Debug for Values<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl fmt::Debug for Values<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries(self.clone()) .finish() @@ -1845,7 +1845,7 @@ impl<'a, K, V> InternalEntry> { /// /// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { map: &'a mut HashMap, } @@ -1859,7 +1859,7 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { /// [`HashMap`]: struct.HashMap.html /// [`Entry`]: enum.Entry.html /// [`raw_entry`]: struct.HashMap.html#method.raw_entry -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// An occupied entry. Occupied(RawOccupiedEntryMut<'a, K, V>), @@ -1871,7 +1871,7 @@ pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { elem: FullBucket>, } @@ -1880,7 +1880,7 @@ pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a> { /// It is part of the [`RawEntryMut`] enum. /// /// [`RawEntryMut`]: enum.RawEntryMut.html -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { elem: VacantEntryState>, hash_builder: &'a S, @@ -1891,7 +1891,7 @@ pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { /// See the [`HashMap::raw_entry`] docs for usage examples. /// /// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> { map: &'a HashMap, } @@ -1901,8 +1901,8 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> where S: BuildHasher, K: Eq + Hash, { - /// Create a `RawEntryMut` from the given key. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + /// Creates a `RawEntryMut` from the given key. + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> where K: Borrow, Q: Hash + Eq @@ -1912,8 +1912,9 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> self.from_key_hashed_nocheck(hasher.finish(), k) } - /// Create a `RawEntryMut` from the given key and its hash. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + /// Creates a `RawEntryMut` from the given key and its hash. + #[inline] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> where K: Borrow, Q: Eq @@ -1921,7 +1922,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> self.from_hash(hash, |q| q.borrow().eq(k)) } - #[cfg(rayon_hash_unstable)] + #[inline] fn search(self, hash: u64, is_match: F, compare_hashes: bool) -> RawEntryMut<'a, K, V, S> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1943,8 +1944,9 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> } } } - /// Create a `RawEntryMut` from the given hash. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + /// Creates a `RawEntryMut` from the given hash. + #[inline] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1954,7 +1956,7 @@ impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> /// Search possible locations for an element with hash `hash` until `is_match` returns true for /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided /// hash. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn search_bucket(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> where for<'b> F: FnMut(&'b K) -> bool, { @@ -1967,7 +1969,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> where S: BuildHasher, { /// Access an entry by key. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key(self, k: &Q) -> Option<(&'a K, &'a V)> where K: Borrow, Q: Hash + Eq @@ -1978,7 +1980,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> } /// Access an entry by a key and its hash. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> where K: Borrow, Q: Hash + Eq @@ -1987,10 +1989,12 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> self.from_hash(hash, |q| q.borrow().eq(k)) } - #[cfg(rayon_hash_unstable)] fn search(self, hash: u64, is_match: F, compare_hashes: bool) -> Option<(&'a K, &'a V)> where F: FnMut(&K) -> bool { + if unsafe { unlikely(self.map.table.size() == 0) } { + return None; + } match search_hashed_nonempty(&self.map.table, SafeHash::new(hash), is_match, @@ -2002,7 +2006,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> } /// Access an entry by hash. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn from_hash(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> where F: FnMut(&K) -> bool { @@ -2012,7 +2016,7 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> /// Search possible locations for an element with hash `hash` until `is_match` returns true for /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided /// hash. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn search_bucket(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> where F: FnMut(&K) -> bool { @@ -2028,18 +2032,17 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// # Examples /// /// ``` - /// #![feature(hash_raw_entry)] - /// use std::collections::HashMap; + /// use rayon_hash::HashMap; /// /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12); /// - /// assert_eq!(map["poneyland"], 12); + /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3); + /// assert_eq!(map["poneyland"], 3); /// - /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12).1 += 10; - /// assert_eq!(map["poneyland"], 22); + /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2; + /// assert_eq!(map["poneyland"], 6); /// ``` - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) where K: Hash, S: BuildHasher, @@ -2056,8 +2059,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// # Examples /// /// ``` - /// #![feature(hash_raw_entry)] - /// use std::collections::HashMap; + /// use rayon_hash::HashMap; /// /// let mut map: HashMap<&str, String> = HashMap::new(); /// @@ -2067,7 +2069,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn or_insert_with(self, default: F) -> (&'a mut K, &'a mut V) where F: FnOnce() -> (K, V), K: Hash, @@ -2088,8 +2090,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// # Examples /// /// ``` - /// #![feature(hash_raw_entry)] - /// use std::collections::HashMap; + /// use rayon_hash::HashMap; /// /// let mut map: HashMap<&str, u32> = HashMap::new(); /// @@ -2105,7 +2106,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// .or_insert("poneyland", 0); /// assert_eq!(map["poneyland"], 43); /// ``` - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn and_modify(self, f: F) -> Self where F: FnOnce(&mut K, &mut V) { @@ -2125,82 +2126,82 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { #[cfg(rayon_hash_unstable)] impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { /// Gets a reference to the key in the entry. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key(&self) -> &K { self.elem.read().0 } /// Gets a mutable reference to the key in the entry. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn key_mut(&mut self) -> &mut K { self.elem.read_mut().0 } /// Converts the entry into a mutable reference to the key in the entry /// with a lifetime bound to the map itself. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key(self) -> &'a mut K { self.elem.into_mut_refs().0 } /// Gets a reference to the value in the entry. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get(&self) -> &V { self.elem.read().1 } /// Converts the OccupiedEntry into a mutable reference to the value in the entry /// with a lifetime bound to the map itself. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_mut(self) -> &'a mut V { self.elem.into_mut_refs().1 } /// Gets a mutable reference to the value in the entry. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_mut(&mut self) -> &mut V { self.elem.read_mut().1 } /// Gets a reference to the key and value in the entry. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_key_value(&mut self) -> (&K, &V) { self.elem.read() } /// Gets a mutable reference to the key and value in the entry. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { self.elem.read_mut() } /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry /// with a lifetime bound to the map itself. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { self.elem.into_mut_refs() } /// Sets the value of the entry, and returns the entry's old value. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert(&mut self, value: V) -> V { mem::replace(self.get_mut(), value) } /// Sets the value of the entry, and returns the entry's old value. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert_key(&mut self, key: K) -> K { mem::replace(self.key_mut(), key) } /// Takes the value out of the entry, and returns it. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn remove(self) -> V { pop_internal(self.elem).1 } /// Take the ownership of the key and value from the map. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn remove_entry(self) -> (K, V) { let (k, v, _) = pop_internal(self.elem); (k, v) @@ -2211,7 +2212,7 @@ impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) where K: Hash, S: BuildHasher, @@ -2223,7 +2224,8 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] + #[inline] + // #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) { let hash = SafeHash::new(hash); let b = match self.elem { @@ -2244,17 +2246,17 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { } } -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] -impl<'a, K, V, S> Debug for RawEntryBuilderMut<'a, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] +impl Debug for RawEntryBuilderMut<'_, K, V, S> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawEntryBuilder") .finish() } } -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] -impl<'a, K: Debug, V: Debug, S> Debug for RawEntryMut<'a, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] +impl Debug for RawEntryMut<'_, K, V, S> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { RawEntryMut::Vacant(ref v) => { f.debug_tuple("RawEntry") @@ -2270,9 +2272,9 @@ impl<'a, K: Debug, V: Debug, S> Debug for RawEntryMut<'a, K, V, S> { } } -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] -impl<'a, K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] +impl Debug for RawOccupiedEntryMut<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawOccupiedEntryMut") .field("key", self.key()) .field("value", self.get()) @@ -2280,17 +2282,17 @@ impl<'a, K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'a, K, V> { } } -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] -impl<'a, K, V, S> Debug for RawVacantEntryMut<'a, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] +impl Debug for RawVacantEntryMut<'_, K, V, S> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawVacantEntryMut") .finish() } } -#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "54043")] -impl<'a, K, V, S> Debug for RawEntryBuilder<'a, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +#[cfg(rayon_hash_unstable)] // #[unstable(feature = "hash_raw_entry", issue = "56167")] +impl Debug for RawEntryBuilder<'_, K, V, S> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawEntryBuilder") .finish() } @@ -2316,8 +2318,8 @@ pub enum Entry<'a, K: 'a, V: 'a> { } // #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Entry<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl Debug for Entry<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Vacant(ref v) => { f.debug_tuple("Entry") @@ -2343,9 +2345,14 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> { elem: FullBucket>, } +// #[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<'a, K: 'a + Send, V: 'a + Send> Send for OccupiedEntry<'a, K, V> {} +// #[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<'a, K: 'a + Sync, V: 'a + Sync> Sync for OccupiedEntry<'a, K, V> {} + // #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl Debug for OccupiedEntry<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OccupiedEntry") .field("key", self.key()) .field("value", self.get()) @@ -2364,9 +2371,14 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> { elem: VacantEntryState>, } +// #[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<'a, K: 'a + Send, V: 'a + Send> Send for VacantEntry<'a, K, V> {} +// #[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<'a, K: 'a + Sync, V: 'a + Sync> Sync for VacantEntry<'a, K, V> {} + // #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a> Debug for VacantEntry<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl Debug for VacantEntry<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("VacantEntry") .field(self.key()) .finish() @@ -2383,10 +2395,7 @@ enum VacantEntryState { } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V, S> IntoIterator for &'a HashMap - where K: Eq + Hash, - S: BuildHasher -{ +impl<'a, K, V, S> IntoIterator for &'a HashMap { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; @@ -2396,10 +2405,7 @@ impl<'a, K, V, S> IntoIterator for &'a HashMap } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V, S> IntoIterator for &'a mut HashMap - where K: Eq + Hash, - S: BuildHasher -{ +impl<'a, K, V, S> IntoIterator for &'a mut HashMap { type Item = (&'a K, &'a mut V); type IntoIter = IterMut<'a, K, V>; @@ -2409,10 +2415,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap } // #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for HashMap - where K: Eq + Hash, - S: BuildHasher -{ +impl IntoIterator for HashMap { type Item = (K, V); type IntoIter = IntoIter; @@ -2452,7 +2455,7 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { +impl ExactSizeIterator for Iter<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() @@ -2460,7 +2463,7 @@ impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K, V> FusedIterator for Iter<'a, K, V> {} +impl FusedIterator for Iter<'_, K, V> {} // #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for IterMut<'a, K, V> { @@ -2476,21 +2479,21 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { +impl ExactSizeIterator for IterMut<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} +impl FusedIterator for IterMut<'_, K, V> {} // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K, V> fmt::Debug for IterMut<'a, K, V> +impl fmt::Debug for IterMut<'_, K, V> where K: fmt::Debug, V: fmt::Debug, { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries(self.inner.iter()) .finish() @@ -2522,7 +2525,7 @@ impl FusedIterator for IntoIter {} // #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries(self.inner.iter()) .finish() @@ -2543,14 +2546,14 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { +impl ExactSizeIterator for Keys<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K, V> FusedIterator for Keys<'a, K, V> {} +impl FusedIterator for Keys<'_, K, V> {} // #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Values<'a, K, V> { @@ -2566,14 +2569,14 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { +impl ExactSizeIterator for Values<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K, V> FusedIterator for Values<'a, K, V> {} +impl FusedIterator for Values<'_, K, V> {} // #[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { @@ -2589,21 +2592,21 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { } } // #[stable(feature = "map_values_mut", since = "1.10.0")] -impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { +impl ExactSizeIterator for ValuesMut<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} +impl FusedIterator for ValuesMut<'_, K, V> {} // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V> +impl fmt::Debug for ValuesMut<'_, K, V> where K: fmt::Debug, V: fmt::Debug, { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries(self.inner.inner.iter()) .finish() @@ -2624,21 +2627,21 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { } } // #[stable(feature = "drain", since = "1.6.0")] -impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { +impl ExactSizeIterator for Drain<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} +impl FusedIterator for Drain<'_, K, V> {} // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K, V> fmt::Debug for Drain<'a, K, V> +impl fmt::Debug for Drain<'_, K, V> where K: fmt::Debug, V: fmt::Debug, { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() .entries(self.inner.iter()) .finish() @@ -2656,12 +2659,12 @@ impl<'a, K, V> Entry<'a, K, V> { /// use rayon_hash::HashMap; /// /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); /// - /// assert_eq!(map["poneyland"], 12); + /// map.entry("poneyland").or_insert(3); + /// assert_eq!(map["poneyland"], 3); /// - /// *map.entry("poneyland").or_insert(12) += 10; - /// assert_eq!(map["poneyland"], 22); + /// *map.entry("poneyland").or_insert(10) *= 2; + /// assert_eq!(map["poneyland"], 6); /// ``` pub fn or_insert(self, default: V) -> &'a mut V { match self { @@ -3202,7 +3205,7 @@ mod test_map { use super::RandomState; use std::cell::RefCell; use rand::{thread_rng, Rng}; - #[cfg(rayon_hash_unstable)] use alloc::CollectionAllocErr::*; + #[cfg(rayon_hash_unstable)] use crate::alloc::CollectionAllocErr::*; #[cfg(rayon_hash_unstable)] use std::mem::size_of; use std::usize; @@ -3472,7 +3475,7 @@ mod test_map { for i in 1..1001 { assert!(m.insert(i, i).is_none()); - for j in 1..i + 1 { + for j in 1..=i { let r = m.get(&j); assert_eq!(r, Some(&j)); } @@ -3491,7 +3494,7 @@ mod test_map { for i in 1..1001 { assert!(m.remove(&i).is_some()); - for j in 1..i + 1 { + for j in 1..=i { assert!(!m.contains_key(&j)); } diff --git a/src/std_hash/mod.rs b/src/std_hash/mod.rs index 62879ac..4441416 100644 --- a/src/std_hash/mod.rs +++ b/src/std_hash/mod.rs @@ -1,13 +1,3 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Unordered containers, implemented as hash-tables pub(crate) mod table; diff --git a/src/std_hash/set.rs b/src/std_hash/set.rs index d93040b..ab40972 100644 --- a/src/std_hash/set.rs +++ b/src/std_hash/set.rs @@ -1,13 +1,3 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::borrow::Borrow; use std::fmt; use std::hash::{Hash, BuildHasher}; @@ -18,7 +8,7 @@ use super::Recover; use super::map::{self, HashMap, Keys, RandomState}; // Future Optimization (FIXME!) -// ============================= +// ============================ // // Iteration over zero sized values is a noop. There is no need // for `bucket.val` in the case of HashSet. I suppose we would need HKT @@ -159,6 +149,118 @@ impl HashSet { } } +impl HashSet { + /// Returns the number of elements the set can hold without reallocating. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashSet; + /// let set: HashSet = HashSet::with_capacity(100); + /// assert!(set.capacity() >= 100); + /// ``` + #[inline] + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.map.capacity() + } + + /// An iterator visiting all elements in arbitrary order. + /// The iterator element type is `&'a T`. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashSet; + /// let mut set = HashSet::new(); + /// set.insert("a"); + /// set.insert("b"); + /// + /// // Will print in an arbitrary order. + /// for x in set.iter() { + /// println!("{}", x); + /// } + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { iter: self.map.keys() } + } + + /// Returns the number of elements in the set. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashSet; + /// + /// let mut v = HashSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1); + /// assert_eq!(v.len(), 1); + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.map.len() + } + + /// Returns `true` if the set contains no elements. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashSet; + /// + /// let mut v = HashSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1); + /// assert!(!v.is_empty()); + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + /// Clears the set, returning all elements in an iterator. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashSet; + /// + /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// assert!(!set.is_empty()); + /// + /// // print 1, 2, 3 in an arbitrary order + /// for i in set.drain() { + /// println!("{}", i); + /// } + /// + /// assert!(set.is_empty()); + /// ``` + #[inline] + // #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self) -> Drain<'_, T> { + Drain { iter: self.map.drain() } + } + + /// Clears the set, removing all values. + /// + /// # Examples + /// + /// ``` + /// use rayon_hash::HashSet; + /// + /// let mut v = HashSet::new(); + /// v.insert(1); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.map.clear() + } +} + impl HashSet where T: Eq + Hash, S: BuildHasher @@ -189,7 +291,7 @@ impl HashSet HashSet { map: HashMap::with_hasher(hasher) } } - /// Creates an empty `HashSet` with with the specified capacity, using + /// 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 @@ -235,21 +337,6 @@ impl HashSet self.map.hasher() } - /// Returns the number of elements the set can hold without reallocating. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashSet; - /// let set: HashSet = HashSet::with_capacity(100); - /// assert!(set.capacity() >= 100); - /// ``` - #[inline] - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn capacity(&self) -> usize { - self.map.capacity() - } - /// Reserves capacity for at least `additional` more elements to be inserted /// in the `HashSet`. The collection may reserve more space to avoid /// frequent reallocations. @@ -314,34 +401,13 @@ impl HashSet /// assert!(set.capacity() >= 2); /// ``` #[inline] - #[cfg(rayon_hash_unstable)] // #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + #[cfg(rayon_hash_unstable)] // #[unstable(feature = "shrink_to", reason = "new API", issue="56431")] pub fn shrink_to(&mut self, min_capacity: usize) { self.map.shrink_to(min_capacity) } - /// An iterator visiting all elements in arbitrary order. - /// The iterator element type is `&'a T`. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a"); - /// set.insert("b"); - /// - /// // Will print in an arbitrary order. - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter { - Iter { iter: self.map.keys() } - } - /// Visits the values representing the difference, - /// i.e. the values that are in `self` but not in `other`. + /// i.e., the values that are in `self` but not in `other`. /// /// # Examples /// @@ -372,7 +438,7 @@ impl HashSet } /// Visits the values representing the symmetric difference, - /// i.e. the values that are in `self` or in `other` but not in both. + /// i.e., the values that are in `self` or in `other` but not in both. /// /// # Examples /// @@ -400,7 +466,7 @@ impl HashSet } /// Visits the values representing the intersection, - /// i.e. the values that are both in `self` and `other`. + /// i.e., the values that are both in `self` and `other`. /// /// # Examples /// @@ -419,14 +485,21 @@ impl HashSet /// ``` // #[stable(feature = "rust1", since = "1.0.0")] pub fn intersection<'a>(&'a self, other: &'a HashSet) -> Intersection<'a, T, S> { - Intersection { - iter: self.iter(), - other, + if self.len() <= other.len() { + Intersection { + iter: self.iter(), + other, + } + } else { + Intersection { + iter: other.iter(), + other: self, + } } } /// Visits the values representing the union, - /// i.e. all the values in `self` or `other`, without duplicates. + /// i.e., all the values in `self` or `other`, without duplicates. /// /// # Examples /// @@ -445,81 +518,15 @@ impl HashSet /// ``` // #[stable(feature = "rust1", since = "1.0.0")] pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, S> { - Union { iter: self.iter().chain(other.difference(self)) } - } - - /// Returns the number of elements in the set. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1); - /// assert_eq!(v.len(), 1); - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn len(&self) -> usize { - self.map.len() - } - - /// Returns true if the set contains no elements. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1); - /// assert!(!v.is_empty()); - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - /// Clears the set, returning all elements in an iterator. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashSet; - /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert!(!set.is_empty()); - /// - /// // print 1, 2, 3 in an arbitrary order - /// for i in set.drain() { - /// println!("{}", i); - /// } - /// - /// assert!(set.is_empty()); - /// ``` - #[inline] - // #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self) -> Drain { - Drain { iter: self.map.drain() } - } - - /// Clears the set, removing all values. - /// - /// # Examples - /// - /// ``` - /// use rayon_hash::HashSet; - /// - /// let mut v = HashSet::new(); - /// v.insert(1); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - // #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) { - self.map.clear() + if self.len() <= other.len() { + Union { + iter: self.iter().chain(other.difference(self)), + } + } else { + Union { + iter: other.iter().chain(self.difference(other)), + } + } } /// Returns `true` if the set contains a value. @@ -593,11 +600,15 @@ impl HashSet /// ``` // #[stable(feature = "rust1", since = "1.0.0")] pub fn is_disjoint(&self, other: &HashSet) -> bool { - self.iter().all(|v| !other.contains(v)) + if self.len() <= other.len() { + self.iter().all(|v| !other.contains(v)) + } else { + other.iter().all(|v| !self.contains(v)) + } } /// Returns `true` if the set is a subset of another, - /// i.e. `other` contains at least all the values in `self`. + /// i.e., `other` contains at least all the values in `self`. /// /// # Examples /// @@ -615,11 +626,15 @@ impl HashSet /// ``` // #[stable(feature = "rust1", since = "1.0.0")] pub fn is_subset(&self, other: &HashSet) -> bool { - self.iter().all(|v| other.contains(v)) + if self.len() <= other.len() { + self.iter().all(|v| other.contains(v)) + } else { + false + } } /// Returns `true` if the set is a superset of another, - /// i.e. `self` contains at least all the values in `other`. + /// i.e., `self` contains at least all the values in `other`. /// /// # Examples /// @@ -686,7 +701,7 @@ impl HashSet Recover::replace(&mut self.map, value) } - /// Removes a value from the set. Returns `true` if the value was + /// Removes a value from the set. Returns whether the value was /// present in the set. /// /// The value may be any borrowed form of the set's value type, but @@ -789,7 +804,7 @@ impl fmt::Debug for HashSet where T: Eq + Hash + fmt::Debug, S: BuildHasher { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_set().entries(self.iter()).finish() } } @@ -838,7 +853,7 @@ impl Default for HashSet } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitOr<&'b HashSet> for &'a HashSet +impl BitOr<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -870,7 +885,7 @@ impl<'a, 'b, T, S> BitOr<&'b HashSet> for &'a HashSet } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitAnd<&'b HashSet> for &'a HashSet +impl BitAnd<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -902,7 +917,7 @@ impl<'a, 'b, T, S> BitAnd<&'b HashSet> for &'a HashSet } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> BitXor<&'b HashSet> for &'a HashSet +impl BitXor<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -934,7 +949,7 @@ impl<'a, 'b, T, S> BitXor<&'b HashSet> for &'a HashSet } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S> Sub<&'b HashSet> for &'a HashSet +impl Sub<&HashSet> for &HashSet where T: Eq + Hash + Clone, S: BuildHasher + Default { @@ -1056,10 +1071,7 @@ pub struct Union<'a, T: 'a, S: 'a> { } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S> IntoIterator for &'a HashSet - where T: Eq + Hash, - S: BuildHasher -{ +impl<'a, T, S> IntoIterator for &'a HashSet { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1069,10 +1081,7 @@ impl<'a, T, S> IntoIterator for &'a HashSet } // #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for HashSet - where T: Eq + Hash, - S: BuildHasher -{ +impl IntoIterator for HashSet { type Item = T; type IntoIter = IntoIter; @@ -1102,8 +1111,8 @@ impl IntoIterator for HashSet } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K> Clone for Iter<'a, K> { - fn clone(&self) -> Iter<'a, K> { +impl Clone for Iter<'_, K> { + fn clone(&self) -> Self { Iter { iter: self.iter.clone() } } } @@ -1119,17 +1128,17 @@ impl<'a, K> Iterator for Iter<'a, K> { } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K> ExactSizeIterator for Iter<'a, K> { +impl ExactSizeIterator for Iter<'_, K> { fn len(&self) -> usize { self.iter.len() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K> FusedIterator for Iter<'a, K> {} +impl FusedIterator for Iter<'_, K> {} // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl fmt::Debug for Iter<'_, K> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } @@ -1156,7 +1165,7 @@ impl FusedIterator for IntoIter {} // #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let entries_iter = self.iter .inner .iter() @@ -1177,17 +1186,17 @@ impl<'a, K> Iterator for Drain<'a, K> { } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K> ExactSizeIterator for Drain<'a, K> { +impl ExactSizeIterator for Drain<'_, K> { fn len(&self) -> usize { self.iter.len() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, K> FusedIterator for Drain<'a, K> {} +impl FusedIterator for Drain<'_, K> {} // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl fmt::Debug for Drain<'_, K> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let entries_iter = self.iter .inner .iter() @@ -1197,8 +1206,8 @@ impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> { } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S> Clone for Intersection<'a, T, S> { - fn clone(&self) -> Intersection<'a, T, S> { +impl Clone for Intersection<'_, T, S> { + fn clone(&self) -> Self { Intersection { iter: self.iter.clone(), ..*self } } } @@ -1226,25 +1235,25 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> +impl fmt::Debug for Intersection<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, T, S> FusedIterator for Intersection<'a, T, S> +impl FusedIterator for Intersection<'_, T, S> where T: Eq + Hash, S: BuildHasher { } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S> Clone for Difference<'a, T, S> { - fn clone(&self) -> Difference<'a, T, S> { +impl Clone for Difference<'_, T, S> { + fn clone(&self) -> Self { Difference { iter: self.iter.clone(), ..*self } } } @@ -1272,25 +1281,25 @@ impl<'a, T, S> Iterator for Difference<'a, T, S> } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, T, S> FusedIterator for Difference<'a, T, S> +impl FusedIterator for Difference<'_, T, S> where T: Eq + Hash, S: BuildHasher { } // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, T, S> fmt::Debug for Difference<'a, T, S> +impl fmt::Debug for Difference<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> { - fn clone(&self) -> SymmetricDifference<'a, T, S> { +impl Clone for SymmetricDifference<'_, T, S> { + fn clone(&self) -> Self { SymmetricDifference { iter: self.iter.clone() } } } @@ -1311,42 +1320,42 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> +impl FusedIterator for SymmetricDifference<'_, T, S> where T: Eq + Hash, S: BuildHasher { } // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> +impl fmt::Debug for SymmetricDifference<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } // #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S> Clone for Union<'a, T, S> { - fn clone(&self) -> Union<'a, T, S> { +impl Clone for Union<'_, T, S> { + fn clone(&self) -> Self { Union { iter: self.iter.clone() } } } // #[stable(feature = "fused", since = "1.26.0")] -impl<'a, T, S> FusedIterator for Union<'a, T, S> +impl FusedIterator for Union<'_, T, S> where T: Eq + Hash, S: BuildHasher { } // #[stable(feature = "std_debug", since = "1.16.0")] -impl<'a, T, S> fmt::Debug for Union<'a, T, S> +impl fmt::Debug for Union<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } @@ -1503,6 +1512,7 @@ mod test_set { fn test_intersection() { let mut a = HashSet::new(); let mut b = HashSet::new(); + assert!(a.intersection(&b).next().is_none()); assert!(a.insert(11)); assert!(a.insert(1)); @@ -1527,6 +1537,22 @@ mod test_set { i += 1 } assert_eq!(i, expected.len()); + + assert!(a.insert(9)); // make a bigger than b + + i = 0; + for x in a.intersection(&b) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); + + i = 0; + for x in b.intersection(&a) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); } #[test] @@ -1582,11 +1608,11 @@ mod test_set { fn test_union() { let mut a = HashSet::new(); let mut b = HashSet::new(); + assert!(a.union(&b).next().is_none()); + assert!(b.union(&a).next().is_none()); assert!(a.insert(1)); assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); assert!(a.insert(11)); assert!(a.insert(16)); assert!(a.insert(19)); @@ -1606,6 +1632,23 @@ mod test_set { i += 1 } assert_eq!(i, expected.len()); + + assert!(a.insert(9)); // make a bigger than b + assert!(a.insert(5)); + + i = 0; + for x in a.union(&b) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); + + i = 0; + for x in b.union(&a) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); } #[test] diff --git a/src/std_hash/table.rs b/src/std_hash/table.rs index cac39ff..6cbe098 100644 --- a/src/std_hash/table.rs +++ b/src/std_hash/table.rs @@ -1,21 +1,10 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use alloc::{self, CollectionAllocErr}; -use ptr::Unique; +use crate::alloc::{self, CollectionAllocErr}; +use crate::ptr::Unique; use std::alloc::{alloc, dealloc, Layout, LayoutErr, handle_alloc_error}; use std::hash::{BuildHasher, Hash, Hasher}; use std::marker; -use std::mem::{size_of, needs_drop}; -use std::mem; +use std::mem::{self, size_of, needs_drop}; use std::ops::{Deref, DerefMut}; use std::ptr::{self, NonNull}; use std::hint; @@ -272,11 +261,11 @@ impl FullBucket { pub fn into_table(self) -> M { self.table } - /// Get the raw index. + /// Gets the raw index. pub fn index(&self) -> usize { self.raw.idx } - /// Get the raw bucket. + /// Gets the raw bucket. pub fn raw(&self) -> RawBucket { self.raw } @@ -294,7 +283,7 @@ impl EmptyBucket { } impl Bucket { - /// Get the raw index. + /// Gets the raw index. pub fn index(&self) -> usize { self.raw.idx } @@ -320,7 +309,7 @@ pub trait Put { } -impl<'t, K, V> Put for &'t mut RawTable { +impl Put for &mut RawTable { unsafe fn borrow_table_mut(&mut self) -> &mut RawTable { *self } @@ -343,6 +332,7 @@ impl Put for FullBucket } impl>> Bucket { + #[inline] pub fn new(table: M, hash: SafeHash) -> Bucket { Bucket::at_index(table, hash.inspect() as usize) } @@ -356,6 +346,7 @@ impl>> Bucket { } } + #[inline] pub fn at_index(table: M, ib_index: usize) -> Bucket { // if capacity is 0, then the RawBucket will be populated with bogus pointers. // This is an uncommon case though, so avoid it in release builds. @@ -525,7 +516,7 @@ impl>> FullBucket { } } - /// Get the distance between this bucket and the 'ideal' location + /// Gets the distance between this bucket and the 'ideal' location /// as determined by the key's hash stored in it. /// /// In the cited blog posts above, this is called the "distance to @@ -668,6 +659,7 @@ impl GapThenFull // Returns a Layout which describes the allocation required for a hash table, // and the offset of the array of (key, value) pairs in the allocation. +#[inline(always)] fn calculate_layout(capacity: usize) -> Result<(Layout, usize), LayoutErr> { let hashes = alloc::Layout::array::(capacity)?; let pairs = alloc::Layout::array::<(K, V)>(capacity)?; @@ -736,6 +728,7 @@ impl RawTable { } } + #[inline(always)] pub(crate) fn raw_bucket_at(&self, index: usize) -> RawBucket { let (_, pairs_offset) = calculate_layout::(self.capacity()) .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }); @@ -750,6 +743,7 @@ impl RawTable { } } + #[inline] fn new_internal( capacity: usize, fallibility: Fallibility, @@ -765,12 +759,14 @@ impl RawTable { /// Tries to create a new raw table from a given capacity. If it cannot allocate, /// it returns with AllocErr. + #[inline] pub fn try_new(capacity: usize) -> Result, CollectionAllocErr> { Self::new_internal(capacity, Fallible) } /// Creates a new raw table from a given capacity. All buckets are /// initially empty. + #[inline] pub fn new(capacity: usize) -> RawTable { match Self::new_internal(capacity, Infallible) { Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), @@ -794,7 +790,7 @@ impl RawTable { self.size = size; } - fn raw_buckets(&self) -> RawBuckets { + fn raw_buckets(&self) -> RawBuckets<'_, K, V> { RawBuckets { raw: self.raw_bucket_at(0), elems_left: self.size, @@ -802,13 +798,13 @@ impl RawTable { } } - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_, K, V> { Iter { iter: self.raw_buckets(), } } - pub fn iter_mut(&mut self) -> IterMut { + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { IterMut { iter: self.raw_buckets(), _marker: marker::PhantomData, @@ -828,7 +824,7 @@ impl RawTable { } } - pub fn drain(&mut self) -> Drain { + pub fn drain(&mut self) -> Drain<'_, K, V> { let RawBuckets { raw, elems_left, .. } = self.raw_buckets(); // Replace the marker regardless of lifetime bounds on parameters. Drain { @@ -860,12 +856,12 @@ impl RawTable { } } - /// Set the table tag + /// Sets the table tag. pub fn set_tag(&mut self, value: bool) { self.hashes.set_tag(value) } - /// Get the table tag + /// Gets the table tag. pub fn tag(&self) -> bool { self.hashes.tag() } @@ -886,8 +882,8 @@ struct RawBuckets<'a, K, V> { } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl<'a, K, V> Clone for RawBuckets<'a, K, V> { - fn clone(&self) -> RawBuckets<'a, K, V> { +impl Clone for RawBuckets<'_, K, V> { + fn clone(&self) -> Self { RawBuckets { raw: self.raw, elems_left: self.elems_left, @@ -922,7 +918,7 @@ impl<'a, K, V> Iterator for RawBuckets<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for RawBuckets<'a, K, V> { +impl ExactSizeIterator for RawBuckets<'_, K, V> { fn len(&self) -> usize { self.elems_left } @@ -933,12 +929,12 @@ pub struct Iter<'a, K: 'a, V: 'a> { iter: RawBuckets<'a, K, V>, } -unsafe impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V> {} -unsafe impl<'a, K: Sync, V: Sync> Send for Iter<'a, K, V> {} +unsafe impl Sync for Iter<'_, K, V> {} +unsafe impl Send for Iter<'_, K, V> {} // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl<'a, K, V> Clone for Iter<'a, K, V> { - fn clone(&self) -> Iter<'a, K, V> { +impl Clone for Iter<'_, K, V> { + fn clone(&self) -> Self { Iter { iter: self.iter.clone(), } @@ -952,13 +948,13 @@ pub struct IterMut<'a, K: 'a, V: 'a> { _marker: marker::PhantomData<&'a mut V>, } -unsafe impl<'a, K: Sync, V: Sync> Sync for IterMut<'a, K, V> {} +unsafe impl Sync for IterMut<'_, K, V> {} // Both K: Sync and K: Send are correct for IterMut's Send impl, // but Send is the more useful bound -unsafe impl<'a, K: Send, V: Send> Send for IterMut<'a, K, V> {} +unsafe impl Send for IterMut<'_, K, V> {} impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> { - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_, K, V> { Iter { iter: self.iter.clone(), } @@ -975,7 +971,7 @@ unsafe impl Sync for IntoIter {} unsafe impl Send for IntoIter {} impl IntoIter { - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_, K, V> { Iter { iter: self.iter.clone(), } @@ -989,11 +985,11 @@ pub struct Drain<'a, K: 'a, V: 'a> { marker: marker::PhantomData<&'a RawTable>, } -unsafe impl<'a, K: Sync, V: Sync> Sync for Drain<'a, K, V> {} -unsafe impl<'a, K: Send, V: Send> Send for Drain<'a, K, V> {} +unsafe impl Sync for Drain<'_, K, V> {} +unsafe impl Send for Drain<'_, K, V> {} impl<'a, K, V> Drain<'a, K, V> { - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_, K, V> { Iter { iter: self.iter.clone(), } @@ -1015,7 +1011,7 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { +impl ExactSizeIterator for Iter<'_, K, V> { fn len(&self) -> usize { self.iter.len() } @@ -1036,7 +1032,7 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { +impl ExactSizeIterator for IterMut<'_, K, V> { fn len(&self) -> usize { self.iter.len() } @@ -1085,13 +1081,13 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { +impl ExactSizeIterator for Drain<'_, K, V> { fn len(&self) -> usize { self.iter.len() } } -impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> { +impl Drop for Drain<'_, K, V> { fn drop(&mut self) { self.for_each(drop); }