Repository: rust-lang/rust
Pull request: feat: reimplement `hash_map!` macro

<!-- homu-ignore:start -->
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r? <reviewer name>
-->
<!-- homu-ignore:end -->

originally implemented in rust-lang/rust#144070, this had to be reverted in rust-lang/rust#148049 due to name ambiguity, as the macro was automatically put into the prelude. now, that rust-lang/rust#139493 has landed, it is possible to have a top-level macro, that is not exported by default, which should make it possible to reland this again.

implements rust-lang/rust#144032
implementation from rust-lang/rust#144070, original author has been added as co-author 
effectively reverts rust-lang/rust#148049

Changed files:
filename: library/std/src/lib.rs
patch: @@ -337,6 +337,8 @@
 #![feature(formatting_options)]
 #![feature(funnel_shifts)]
 #![feature(generic_atomic)]
+#![feature(hash_map_internals)]
+#![feature(hash_map_macro)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
 #![feature(hint_must_use)]

filename: library/std/src/macros.rs
patch: @@ -418,3 +418,79 @@ pub macro dbg_internal {
         )
     },
 }
+
+#[doc(hidden)]
+#[macro_export]
+#[allow_internal_unstable(hash_map_internals)]
+#[unstable(feature = "hash_map_internals", issue = "none")]
+macro_rules! repetition_utils {
+    (@count $($tokens:tt),*) => {{
+        [$($crate::repetition_utils!(@replace $tokens => ())),*].len()
+    }};
+
+    (@replace $x:tt => $y:tt) => { $y }
+}
+
+/// Creates a [`HashMap`] containing the arguments.
+///
+/// `hash_map!` allows specifying the entries that make
+/// up the [`HashMap`] where the key and value are separated by a `=>`.
+///
+/// The entries are separated by commas with a trailing comma being allowed.
+///
+/// It is semantically equivalent to using repeated [`HashMap::insert`]
+/// on a newly created hashmap.
+///
+/// `hash_map!` will attempt to avoid repeated reallocations by
+/// using [`HashMap::with_capacity`].
+///
+/// # Examples
+///
+/// ```rust
+/// #![feature(hash_map_macro)]
+/// use std::hash_map;
+///
+/// let map = hash_map! {
+///     "key" => "value",
+///     "key1" => "value1"
+/// };
+///
+/// assert_eq!(map.get("key"), Some(&"value"));
+/// assert_eq!(map.get("key1"), Some(&"value1"));
+/// assert!(map.get("brrrrrrooooommm").is_none());
+/// ```
+///
+/// And with a trailing comma
+///
+///```rust
+/// #![feature(hash_map_macro)]
+/// use std::hash_map;
+///
+/// let map = hash_map! {
+///     "key" => "value", // notice the ,
+/// };
+///
+/// assert_eq!(map.get("key"), Some(&"value"));
+/// ```
+///
+/// The key and value are moved into the HashMap.
+///
+/// [`HashMap`]: crate::collections::HashMap
+/// [`HashMap::insert`]: crate::collections::HashMap::insert
+/// [`HashMap::with_capacity`]: crate::collections::HashMap::with_capacity
+#[macro_export]
+#[allow_internal_unstable(hash_map_internals)]
+#[unstable(feature = "hash_map_macro", issue = "144032")]
+macro_rules! hash_map {
+    () => {{
+        $crate::collections::HashMap::new()
+    }};
+
+    ( $( $key:expr => $value:expr ),* $(,)? ) => {{
+        let mut map = $crate::collections::HashMap::with_capacity(
+            const { $crate::repetition_utils!(@count $($key),*) }
+        );
+        $( map.insert($key, $value); )*
+        map
+    }}
+}