Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
76 changes: 76 additions & 0 deletions library/std/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,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(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious as to why this is implemented this way instead of using the From<[T;N]> impl. Wouldn't that be simpler, as it would remove the need for the repetition count machinery?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see this comment on the thread of the original implementation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, yeah that's a good reason

const { $crate::repetition_utils!(@count $($key),*) }
);
$( map.insert($key, $value); )*
map
}}
}
Loading