Skip to content

Commit

Permalink
Auto merge of #84111 - bstrie:hashfrom, r=joshtriplett
Browse files Browse the repository at this point in the history
Stabilize `impl From<[(K, V); N]> for HashMap` (and friends)

In addition to allowing HashMap to participate in Into/From conversion, this adds the long-requested ability to use constructor-like syntax for initializing a HashMap:
```rust
let map = HashMap::from([
    (1, 2),
    (3, 4),
    (5, 6)
]);
```
This addition is highly motivated by existing precedence, e.g. it is already possible to similarly construct a Vec from a fixed-size array:
```rust
let vec = Vec::from([1, 2, 3]);
```
...and it is already possible to collect a Vec of tuples into a HashMap (and vice-versa):
```rust
let vec = Vec::from([(1, 2)]);
let map: HashMap<_, _> = vec.into_iter().collect();
let vec: Vec<(_, _)> = map.into_iter().collect();
```
...and of course it is likewise possible to collect a fixed-size array of tuples into a HashMap ([but not vice-versa just yet](rust-lang/rust#81615)):
```rust
let arr = [(1, 2)];
let map: HashMap<_, _> = std::array::IntoIter::new(arr).collect();
```
Therefore this addition seems like a no-brainer.

As for any impl, this would be insta-stable.
  • Loading branch information
bors committed Jul 24, 2021
2 parents 89bd3ba + c909b43 commit 40c1055
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 1 deletion.
29 changes: 28 additions & 1 deletion collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,20 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
/// }
/// ```
///
/// `BTreeMap` also implements an [`Entry API`], which allows for more complex
/// A `BTreeMap` with a known list of items can be initialized from an array:
///
/// ```
/// use std::collections::BTreeMap;
///
/// let solar_distance = BTreeMap::from([
/// ("Mercury", 0.4),
/// ("Venus", 0.7),
/// ("Earth", 1.0),
/// ("Mars", 1.5),
/// ]);
/// ```
///
/// `BTreeMap` implements an [`Entry API`], which allows for complex
/// methods of getting, setting, updating and removing keys and their values:
///
/// [`Entry API`]: BTreeMap::entry
Expand Down Expand Up @@ -2012,6 +2025,20 @@ where
}
}

#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<K: Ord, V, const N: usize> From<[(K, V); N]> for BTreeMap<K, V> {
/// ```
/// use std::collections::BTreeMap;
///
/// let map1 = BTreeMap::from([(1, 2), (3, 4)]);
/// let map2: BTreeMap<_, _> = [(1, 2), (3, 4)].into();
/// assert_eq!(map1, map2);
/// ```
fn from(arr: [(K, V); N]) -> Self {
core::array::IntoIter::new(arr).collect()
}
}

impl<K, V> BTreeMap<K, V> {
/// Gets an iterator over the entries of the map, sorted by key.
///
Expand Down
7 changes: 7 additions & 0 deletions collections/btree/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2173,3 +2173,10 @@ fn test_insert_remove_intertwined_ord_chaos() {
}
map.check_invariants();
}

#[test]
fn from_array() {
let map = BTreeMap::from([(1, 2), (3, 4)]);
let unordered_duplicates = BTreeMap::from([(3, 4), (1, 2), (1, 2)]);
assert_eq!(map, unordered_duplicates);
}
22 changes: 22 additions & 0 deletions collections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ use super::Recover;
/// println!("{}", book);
/// }
/// ```
///
/// A `BTreeSet` with a known list of items can be initialized from an array:
///
/// ```
/// use std::collections::BTreeSet;
///
/// let set = BTreeSet::from([1, 2, 3]);
/// ```
#[derive(Hash, PartialEq, Eq, Ord, PartialOrd)]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeSet")]
Expand Down Expand Up @@ -1057,6 +1065,20 @@ impl<T: Ord> FromIterator<T> for BTreeSet<T> {
}
}

#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<T: Ord, const N: usize> From<[T; N]> for BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let set1 = BTreeSet::from([1, 2, 3, 4]);
/// let set2: BTreeSet<_> = [1, 2, 3, 4].into();
/// assert_eq!(set1, set2);
/// ```
fn from(arr: [T; N]) -> Self {
core::array::IntoIter::new(arr).collect()
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for BTreeSet<T> {
type Item = T;
Expand Down
7 changes: 7 additions & 0 deletions collections/btree/set/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,3 +738,10 @@ fn test_split_off_large_random_sorted() {
assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
}

#[test]
fn from_array() {
let set = BTreeSet::from([1, 2, 3, 4]);
let unordered_duplicates = BTreeSet::from([4, 1, 4, 3, 2]);
assert_eq!(set, unordered_duplicates);
}

0 comments on commit 40c1055

Please sign in to comment.