about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-12-01 10:39:09 +0100
committerRalf Jung <post@ralfj.de>2024-12-02 16:34:39 +0100
commit3a9bc76f809634b0ae9844147766818a1bdcd32b (patch)
tree5e18a69f102fbc4e9108d158257d8de28669c13b
parent3bff51ea912d4dfd9caa1e3bc6f68352618208a7 (diff)
downloadrust-3a9bc76f809634b0ae9844147766818a1bdcd32b.tar.gz
rust-3a9bc76f809634b0ae9844147766818a1bdcd32b.zip
stabilize const_collections_with_hasher and build_hasher_default_const_new
-rw-r--r--library/core/src/hash/mod.rs6
-rw-r--r--library/std/src/collections/hash/map.rs24
-rw-r--r--library/std/src/collections/hash/set.rs24
-rw-r--r--library/std/src/lib.rs1
4 files changed, 49 insertions, 6 deletions
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 061690e88dd..84bbf985e8b 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -752,10 +752,10 @@ pub struct BuildHasherDefault<H>(marker::PhantomData<fn() -> H>);
 
 impl<H> BuildHasherDefault<H> {
     /// Creates a new BuildHasherDefault for Hasher `H`.
-    #[unstable(
+    #[stable(feature = "build_hasher_default_const_new", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(
         feature = "build_hasher_default_const_new",
-        issue = "123197",
-        reason = "recently added"
+        since = "CURRENT_RUSTC_VERSION"
     )]
     pub const fn new() -> Self {
         BuildHasherDefault(marker::PhantomData)
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 09c0b61fb2b..59dcdfd08cb 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -204,6 +204,25 @@ use crate::ops::Index;
 ///     println!("{viking:?} has {health} hp");
 /// }
 /// ```
+///
+/// # Usage in `const` and `static`
+///
+/// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed,
+/// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the
+/// initializer of a `const` or `static` item, you will have to use a different hasher that does not
+/// involve a random seed, as demonstrated in the following example. **`HashMap` constructed this
+/// way are not resistant against HashDoS!**
+///
+/// ```rust
+/// use std::collections::HashMap;
+/// use std::hash::{BuildHasherDefault, DefaultHasher};
+/// use std::sync::Mutex;
+///
+/// const EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> =
+///     HashMap::with_hasher(BuildHasherDefault::new());
+/// static MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> =
+///     Mutex::new(HashMap::with_hasher(BuildHasherDefault::new()));
+/// ```
 
 #[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -277,7 +296,10 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
+    #[rustc_const_stable(
+        feature = "const_collections_with_hasher",
+        since = "CURRENT_RUSTC_VERSION"
+    )]
     pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap { base: base::HashMap::with_hasher(hash_builder) }
     }
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 21a73259f61..2a481dbaa62 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -101,6 +101,25 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub};
 /// [`HashMap`]: crate::collections::HashMap
 /// [`RefCell`]: crate::cell::RefCell
 /// [`Cell`]: crate::cell::Cell
+///
+/// # Usage in `const` and `static`
+///
+/// Like `HashMap`, `HashSet` is randomly seeded: each `HashSet` instance uses a different seed,
+/// which means that `HashSet::new` cannot be used in const context. To construct a `HashSet` in the
+/// initializer of a `const` or `static` item, you will have to use a different hasher that does not
+/// involve a random seed, as demonstrated in the following example. **`HashSet` constructed this
+/// way are not resistant against HashDoS!**
+///
+/// ```rust
+/// use std::collections::HashSet;
+/// use std::hash::{BuildHasherDefault, DefaultHasher};
+/// use std::sync::Mutex;
+///
+/// const EMPTY_SET: HashSet<String, BuildHasherDefault<DefaultHasher>> =
+///     HashSet::with_hasher(BuildHasherDefault::new());
+/// static SET: Mutex<HashSet<String, BuildHasherDefault<DefaultHasher>>> =
+///     Mutex::new(HashSet::with_hasher(BuildHasherDefault::new()));
+/// ```
 #[cfg_attr(not(test), rustc_diagnostic_item = "HashSet")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashSet<T, S = RandomState> {
@@ -369,7 +388,10 @@ impl<T, S> HashSet<T, S> {
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
+    #[rustc_const_stable(
+        feature = "const_collections_with_hasher",
+        since = "CURRENT_RUSTC_VERSION"
+    )]
     pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
         HashSet { base: base::HashSet::with_hasher(hasher) }
     }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 143878170f0..585946c1d50 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -320,7 +320,6 @@
 // Library features (core):
 // tidy-alphabetical-start
 #![feature(array_chunks)]
-#![feature(build_hasher_default_const_new)]
 #![feature(c_str_module)]
 #![feature(char_internals)]
 #![feature(clone_to_uninit)]