Skip to content

Commit 2a20133

Browse files
authored
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.
2 parents 92d8e82 + 48859db commit 2a20133

File tree

4 files changed

+76
-90
lines changed

4 files changed

+76
-90
lines changed

src/libstd/collections/hash/map.rs

+62-64
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ pub struct HashMap<K, V, S = RandomState> {
203203
base: base::HashMap<K, V, S>,
204204
}
205205

206-
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
206+
impl<K, V> HashMap<K, V, RandomState> {
207207
/// Creates an empty `HashMap`.
208208
///
209209
/// The hash map is initially created with a capacity of 0, so it will not allocate until it
@@ -240,6 +240,59 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
240240
}
241241

242242
impl<K, V, S> HashMap<K, V, S> {
243+
/// Creates an empty `HashMap` which will use the given hash builder to hash
244+
/// keys.
245+
///
246+
/// The created map has the default initial capacity.
247+
///
248+
/// Warning: `hash_builder` is normally randomly generated, and
249+
/// is designed to allow HashMaps to be resistant to attacks that
250+
/// cause many collisions and very poor performance. Setting it
251+
/// manually using this function can expose a DoS attack vector.
252+
///
253+
/// # Examples
254+
///
255+
/// ```
256+
/// use std::collections::HashMap;
257+
/// use std::collections::hash_map::RandomState;
258+
///
259+
/// let s = RandomState::new();
260+
/// let mut map = HashMap::with_hasher(s);
261+
/// map.insert(1, 2);
262+
/// ```
263+
#[inline]
264+
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
265+
pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
266+
HashMap { base: base::HashMap::with_hasher(hash_builder) }
267+
}
268+
269+
/// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
270+
/// to hash the keys.
271+
///
272+
/// The hash map will be able to hold at least `capacity` elements without
273+
/// reallocating. If `capacity` is 0, the hash map will not allocate.
274+
///
275+
/// Warning: `hash_builder` is normally randomly generated, and
276+
/// is designed to allow HashMaps to be resistant to attacks that
277+
/// cause many collisions and very poor performance. Setting it
278+
/// manually using this function can expose a DoS attack vector.
279+
///
280+
/// # Examples
281+
///
282+
/// ```
283+
/// use std::collections::HashMap;
284+
/// use std::collections::hash_map::RandomState;
285+
///
286+
/// let s = RandomState::new();
287+
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
288+
/// map.insert(1, 2);
289+
/// ```
290+
#[inline]
291+
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
292+
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
293+
HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
294+
}
295+
243296
/// Returns the number of elements the map can hold without reallocating.
244297
///
245298
/// This number is a lower bound; the `HashMap<K, V>` might be able to hold
@@ -457,65 +510,6 @@ impl<K, V, S> HashMap<K, V, S> {
457510
pub fn clear(&mut self) {
458511
self.base.clear();
459512
}
460-
}
461-
462-
impl<K, V, S> HashMap<K, V, S>
463-
where
464-
K: Eq + Hash,
465-
S: BuildHasher,
466-
{
467-
/// Creates an empty `HashMap` which will use the given hash builder to hash
468-
/// keys.
469-
///
470-
/// The created map has the default initial capacity.
471-
///
472-
/// Warning: `hash_builder` is normally randomly generated, and
473-
/// is designed to allow HashMaps to be resistant to attacks that
474-
/// cause many collisions and very poor performance. Setting it
475-
/// manually using this function can expose a DoS attack vector.
476-
///
477-
/// # Examples
478-
///
479-
/// ```
480-
/// use std::collections::HashMap;
481-
/// use std::collections::hash_map::RandomState;
482-
///
483-
/// let s = RandomState::new();
484-
/// let mut map = HashMap::with_hasher(s);
485-
/// map.insert(1, 2);
486-
/// ```
487-
#[inline]
488-
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
489-
pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
490-
HashMap { base: base::HashMap::with_hasher(hash_builder) }
491-
}
492-
493-
/// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
494-
/// to hash the keys.
495-
///
496-
/// The hash map will be able to hold at least `capacity` elements without
497-
/// reallocating. If `capacity` is 0, the hash map will not allocate.
498-
///
499-
/// Warning: `hash_builder` is normally randomly generated, and
500-
/// is designed to allow HashMaps to be resistant to attacks that
501-
/// cause many collisions and very poor performance. Setting it
502-
/// manually using this function can expose a DoS attack vector.
503-
///
504-
/// # Examples
505-
///
506-
/// ```
507-
/// use std::collections::HashMap;
508-
/// use std::collections::hash_map::RandomState;
509-
///
510-
/// let s = RandomState::new();
511-
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
512-
/// map.insert(1, 2);
513-
/// ```
514-
#[inline]
515-
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
516-
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
517-
HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
518-
}
519513

520514
/// Returns a reference to the map's [`BuildHasher`].
521515
///
@@ -536,7 +530,13 @@ where
536530
pub fn hasher(&self) -> &S {
537531
self.base.hasher()
538532
}
533+
}
539534

535+
impl<K, V, S> HashMap<K, V, S>
536+
where
537+
K: Eq + Hash,
538+
S: BuildHasher,
539+
{
540540
/// Reserves capacity for at least `additional` more elements to be inserted
541541
/// in the `HashMap`. The collection may reserve more space to avoid
542542
/// frequent reallocations.
@@ -984,9 +984,8 @@ where
984984
#[stable(feature = "rust1", since = "1.0.0")]
985985
impl<K, V, S> Debug for HashMap<K, V, S>
986986
where
987-
K: Eq + Hash + Debug,
987+
K: Debug,
988988
V: Debug,
989-
S: BuildHasher,
990989
{
991990
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
992991
f.debug_map().entries(self.iter()).finish()
@@ -996,8 +995,7 @@ where
996995
#[stable(feature = "rust1", since = "1.0.0")]
997996
impl<K, V, S> Default for HashMap<K, V, S>
998997
where
999-
K: Eq + Hash,
1000-
S: BuildHasher + Default,
998+
S: Default,
1001999
{
10021000
/// Creates an empty `HashMap<K, V, S>`, with the `Default` value for the hasher.
10031001
#[inline]

src/libstd/collections/hash/set.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub struct HashSet<T, S = RandomState> {
110110
map: HashMap<T, (), S>,
111111
}
112112

113-
impl<T: Hash + Eq> HashSet<T, RandomState> {
113+
impl<T> HashSet<T, RandomState> {
114114
/// Creates an empty `HashSet`.
115115
///
116116
/// The hash set is initially created with a capacity of 0, so it will not allocate until it
@@ -261,13 +261,7 @@ impl<T, S> HashSet<T, S> {
261261
pub fn clear(&mut self) {
262262
self.map.clear()
263263
}
264-
}
265264

266-
impl<T, S> HashSet<T, S>
267-
where
268-
T: Eq + Hash,
269-
S: BuildHasher,
270-
{
271265
/// Creates a new empty hash set which will use the given hasher to hash
272266
/// keys.
273267
///
@@ -340,7 +334,13 @@ where
340334
pub fn hasher(&self) -> &S {
341335
self.map.hasher()
342336
}
337+
}
343338

339+
impl<T, S> HashSet<T, S>
340+
where
341+
T: Eq + Hash,
342+
S: BuildHasher,
343+
{
344344
/// Reserves capacity for at least `additional` more elements to be inserted
345345
/// in the `HashSet`. The collection may reserve more space to avoid
346346
/// frequent reallocations.
@@ -928,8 +928,7 @@ where
928928
#[stable(feature = "rust1", since = "1.0.0")]
929929
impl<T, S> fmt::Debug for HashSet<T, S>
930930
where
931-
T: Eq + Hash + fmt::Debug,
932-
S: BuildHasher,
931+
T: fmt::Debug,
933932
{
934933
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
935934
f.debug_set().entries(self.iter()).finish()
@@ -977,8 +976,7 @@ where
977976
#[stable(feature = "rust1", since = "1.0.0")]
978977
impl<T, S> Default for HashSet<T, S>
979978
where
980-
T: Eq + Hash,
981-
S: BuildHasher + Default,
979+
S: Default,
982980
{
983981
/// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
984982
#[inline]

src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ pub fn no_debug() {
66
pub fn no_hash() {
77
use std::collections::HashSet;
88
let mut set = HashSet::new();
9-
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
109
set.insert([0_usize; 33]);
1110
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
1211
}

src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr

+5-14
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,15 @@ LL | println!("{:?}", [0_usize; 33]);
99
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
1010

1111
error[E0277]: arrays only have std trait implementations for lengths 0..=32
12-
--> $DIR/core-traits-no-impls-length-33.rs:10:16
12+
--> $DIR/core-traits-no-impls-length-33.rs:9:16
1313
|
1414
LL | set.insert([0_usize; 33]);
1515
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
1616
|
1717
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
1818

19-
error[E0277]: arrays only have std trait implementations for lengths 0..=32
20-
--> $DIR/core-traits-no-impls-length-33.rs:8:19
21-
|
22-
LL | let mut set = HashSet::new();
23-
| ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
24-
|
25-
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
26-
= note: required by `std::collections::HashSet::<T>::new`
27-
2819
error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]`
29-
--> $DIR/core-traits-no-impls-length-33.rs:15:19
20+
--> $DIR/core-traits-no-impls-length-33.rs:14:19
3021
|
3122
LL | [0_usize; 33] == [1_usize; 33]
3223
| ------------- ^^ ------------- [usize; 33]
@@ -36,7 +27,7 @@ LL | [0_usize; 33] == [1_usize; 33]
3627
= note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]`
3728

3829
error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]`
39-
--> $DIR/core-traits-no-impls-length-33.rs:20:19
30+
--> $DIR/core-traits-no-impls-length-33.rs:19:19
4031
|
4132
LL | [0_usize; 33] < [1_usize; 33]
4233
| ------------- ^ ------------- [usize; 33]
@@ -46,7 +37,7 @@ LL | [0_usize; 33] < [1_usize; 33]
4637
= note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]`
4738

4839
error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
49-
--> $DIR/core-traits-no-impls-length-33.rs:25:14
40+
--> $DIR/core-traits-no-impls-length-33.rs:24:14
5041
|
5142
LL | for _ in &[0_usize; 33] {
5243
| ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]`
@@ -58,7 +49,7 @@ LL | for _ in &[0_usize; 33] {
5849
<&'a mut [T] as std::iter::IntoIterator>
5950
= note: required by `std::iter::IntoIterator::into_iter`
6051

61-
error: aborting due to 6 previous errors
52+
error: aborting due to 5 previous errors
6253

6354
Some errors have detailed explanations: E0277, E0369.
6455
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)