Rollup merge of #67642 - Mark-Simulacrum:relax-bounds, r=Amanieu

Relax bounds on HashMap/HashSet

These APIs changed from the old bound listed to the new bound (possibly empty):

K: Hash + Eq -> K
* new
* with_capacity

K: Eq + Hash, S: BuildHasher -> K, S
* with_hasher
* with_capacity_and_hasher
* hasher

K: Eq + Hash + Debug -> K: Debug
S: BuildHasher -> S
HashMap as Debug

K: Eq + Hash -> K
S: BuildHasher + Default -> S: Default
HashMap as Default

Resolves #44777.
This commit is contained in:
Dylan DPC 2020-02-13 02:52:46 +01:00 committed by GitHub
commit 2a201336ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 90 deletions

View File

@ -203,7 +203,7 @@ pub struct HashMap<K, V, S = RandomState> {
base: base::HashMap<K, V, S>,
}
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
impl<K, V> HashMap<K, V, RandomState> {
/// Creates an empty `HashMap`.
///
/// The hash map is initially created with a capacity of 0, so it will not allocate until it
@ -240,6 +240,59 @@ pub fn with_capacity(capacity: usize) -> HashMap<K, V, RandomState> {
}
impl<K, V, S> HashMap<K, V, S> {
/// Creates an empty `HashMap` which will use the given hash builder to hash
/// keys.
///
/// 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 std::collections::HashMap;
/// use std::collections::hash_map::RandomState;
///
/// let s = RandomState::new();
/// let mut map = HashMap::with_hasher(s);
/// map.insert(1, 2);
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
HashMap { base: base::HashMap::with_hasher(hash_builder) }
}
/// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
/// to hash the keys.
///
/// 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 std::collections::HashMap;
/// use std::collections::hash_map::RandomState;
///
/// let s = RandomState::new();
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
/// map.insert(1, 2);
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
}
/// Returns the number of elements the map can hold without reallocating.
///
/// This number is a lower bound; the `HashMap<K, V>` might be able to hold
@ -457,65 +510,6 @@ pub fn drain(&mut self) -> Drain<'_, K, V> {
pub fn clear(&mut self) {
self.base.clear();
}
}
impl<K, V, S> HashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
/// Creates an empty `HashMap` which will use the given hash builder to hash
/// keys.
///
/// 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 std::collections::HashMap;
/// use std::collections::hash_map::RandomState;
///
/// let s = RandomState::new();
/// let mut map = HashMap::with_hasher(s);
/// map.insert(1, 2);
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
HashMap { base: base::HashMap::with_hasher(hash_builder) }
}
/// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
/// to hash the keys.
///
/// 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 std::collections::HashMap;
/// use std::collections::hash_map::RandomState;
///
/// let s = RandomState::new();
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
/// map.insert(1, 2);
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
}
/// Returns a reference to the map's [`BuildHasher`].
///
@ -536,7 +530,13 @@ pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K,
pub fn hasher(&self) -> &S {
self.base.hasher()
}
}
impl<K, V, S> HashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
/// Reserves capacity for at least `additional` more elements to be inserted
/// in the `HashMap`. The collection may reserve more space to avoid
/// frequent reallocations.
@ -984,9 +984,8 @@ impl<K, V, S> Eq for HashMap<K, V, S>
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S> Debug for HashMap<K, V, S>
where
K: Eq + Hash + Debug,
K: Debug,
V: Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
@ -996,8 +995,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S> Default for HashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher + Default,
S: Default,
{
/// Creates an empty `HashMap<K, V, S>`, with the `Default` value for the hasher.
#[inline]

View File

@ -110,7 +110,7 @@ pub struct HashSet<T, S = RandomState> {
map: HashMap<T, (), S>,
}
impl<T: Hash + Eq> HashSet<T, RandomState> {
impl<T> HashSet<T, RandomState> {
/// Creates an empty `HashSet`.
///
/// The hash set is initially created with a capacity of 0, so it will not allocate until it
@ -261,13 +261,7 @@ pub fn drain(&mut self) -> Drain<'_, T> {
pub fn clear(&mut self) {
self.map.clear()
}
}
impl<T, S> HashSet<T, S>
where
T: Eq + Hash,
S: BuildHasher,
{
/// Creates a new empty hash set which will use the given hasher to hash
/// keys.
///
@ -340,7 +334,13 @@ pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S> {
pub fn hasher(&self) -> &S {
self.map.hasher()
}
}
impl<T, S> HashSet<T, S>
where
T: Eq + Hash,
S: BuildHasher,
{
/// Reserves capacity for at least `additional` more elements to be inserted
/// in the `HashSet`. The collection may reserve more space to avoid
/// frequent reallocations.
@ -928,8 +928,7 @@ impl<T, S> Eq for HashSet<T, S>
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S> fmt::Debug for HashSet<T, S>
where
T: Eq + Hash + fmt::Debug,
S: BuildHasher,
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
@ -977,8 +976,7 @@ fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S> Default for HashSet<T, S>
where
T: Eq + Hash,
S: BuildHasher + Default,
S: Default,
{
/// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
#[inline]

View File

@ -6,7 +6,6 @@ pub fn no_debug() {
pub fn no_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
set.insert([0_usize; 33]);
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
}

View File

@ -9,24 +9,15 @@ LL | println!("{:?}", [0_usize; 33]);
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/core-traits-no-impls-length-33.rs:10:16
--> $DIR/core-traits-no-impls-length-33.rs:9:16
|
LL | set.insert([0_usize; 33]);
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
|
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/core-traits-no-impls-length-33.rs:8:19
|
LL | let mut set = HashSet::new();
| ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
|
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
= note: required by `std::collections::HashSet::<T>::new`
error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]`
--> $DIR/core-traits-no-impls-length-33.rs:15:19
--> $DIR/core-traits-no-impls-length-33.rs:14:19
|
LL | [0_usize; 33] == [1_usize; 33]
| ------------- ^^ ------------- [usize; 33]
@ -36,7 +27,7 @@ LL | [0_usize; 33] == [1_usize; 33]
= note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]`
error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]`
--> $DIR/core-traits-no-impls-length-33.rs:20:19
--> $DIR/core-traits-no-impls-length-33.rs:19:19
|
LL | [0_usize; 33] < [1_usize; 33]
| ------------- ^ ------------- [usize; 33]
@ -46,7 +37,7 @@ LL | [0_usize; 33] < [1_usize; 33]
= note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]`
error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
--> $DIR/core-traits-no-impls-length-33.rs:25:14
--> $DIR/core-traits-no-impls-length-33.rs:24:14
|
LL | for _ in &[0_usize; 33] {
| ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]`
@ -58,7 +49,7 @@ LL | for _ in &[0_usize; 33] {
<&'a mut [T] as std::iter::IntoIterator>
= note: required by `std::iter::IntoIterator::into_iter`
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0369.
For more information about an error, try `rustc --explain E0277`.