]> git.lizzy.rs Git - rust.git/commitdiff
impl From<[(K, V); N]> for std::collections
authorbstrie <865233+bstrie@users.noreply.github.com>
Sun, 11 Apr 2021 22:38:44 +0000 (18:38 -0400)
committerbstrie <865233+bstrie@users.noreply.github.com>
Wed, 30 Jun 2021 21:28:17 +0000 (17:28 -0400)
12 files changed:
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/map/tests.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/btree/set/tests.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/vec/mod.rs
library/std/src/collections/hash/map.rs
library/std/src/collections/hash/map/tests.rs
library/std/src/collections/hash/set.rs
library/std/src/collections/hash/set/tests.rs

index bf9f7432fb5367ad306b743a6b6f2d7ce96b92d7..2f999a10a961095433c8f3dc17dc910b546f746c 100644 (file)
 /// assert!(heap.is_empty())
 /// ```
 ///
+/// A `BinaryHeap` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::BinaryHeap;
+///
+/// let heap = BinaryHeap::from([1, 5, 2]);
+/// ```
+///
 /// ## Min-heap
 ///
 /// Either `std::cmp::Reverse` or a custom `Ord` implementation can be used to
@@ -1443,6 +1451,22 @@ fn from(vec: Vec<T>) -> BinaryHeap<T> {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.55.0")]
+impl<T: Ord, const N: usize> From<[T; N]> for BinaryHeap<T> {
+    /// ```
+    /// use std::collections::BinaryHeap;
+    ///
+    /// let mut h1 = BinaryHeap::from([1, 4, 2, 3]);
+    /// let mut h2: BinaryHeap<_> = [1, 4, 2, 3].into();
+    /// while let Some((a, b)) = h1.pop().zip(h2.pop()) {
+    ///     assert_eq!(a, b);
+    /// }
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
+
 #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T> From<BinaryHeap<T>> for Vec<T> {
     /// Converts a `BinaryHeap<T>` into a `Vec<T>`.
index a0dbb289252f6364eb0c276a1e3ca7fac323974c..708389579dbcfb2731f9cf9285cf555404f87e99 100644 (file)
 /// }
 /// ```
 ///
-/// `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
@@ -2030,6 +2043,20 @@ fn index(&self, key: &Q) -> &V {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.55.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.
     ///
index 3a74b6a6fa85c8f29d366769df6b37ce1b30a2c0..1e61692b7c63cb65be66a7d3ea5c8d019e1fbee7 100644 (file)
@@ -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);
+}
index a331b8d8e4bbbe5e87009de2ee5bf539827449f0..56c2cb56b5ba597d9c8e0dbb0d2cb8ba31ed5d8a 100644 (file)
 ///     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")]
@@ -1057,6 +1065,20 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.55.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;
index 4cb6e3d6619dcb05ac25c1154f3151ee0b1a6343..de7a10dca7b8c5ccfe1c80d3924c26a5d4a1703a 100644 (file)
@@ -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);
+}
index a5481fd175e307cb5e86deb9c0bc00bd974af6b4..8b978a4e806e7a1bd1ddff1cdb7d7610c405eb75 100644 (file)
 /// The `LinkedList` allows pushing and popping elements at either end
 /// in constant time.
 ///
+/// A `LinkedList` with a known list of items can be initialized from an array:
+/// ```
+/// use std::collections::LinkedList;
+///
+/// let list = LinkedList::from([1, 2, 3]);
+/// ```
+///
 /// NOTE: It is almost always better to use `Vec` or `VecDeque` because
 /// array-based containers are generally faster,
 /// more memory efficient, and make better use of CPU cache.
@@ -1767,6 +1774,20 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.55.0")]
+impl<T, const N: usize> From<[T; N]> for LinkedList<T> {
+    /// ```
+    /// use std::collections::LinkedList;
+    ///
+    /// let list1 = LinkedList::from([1, 2, 3, 4]);
+    /// let list2: LinkedList<_> = [1, 2, 3, 4].into();
+    /// assert_eq!(list1, list2);
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
+
 // Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
 #[allow(dead_code)]
 fn assert_covariance() {
index d3e70991ad5187bcee4500d008fe65bd3d56386a..98514b43e7f52be1e50050424a2d177517908cb1 100644 (file)
 /// push onto the back in this manner, and iterating over `VecDeque` goes front
 /// to back.
 ///
+/// A `VecDeque` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::VecDeque;
+///
+/// let deq = VecDeque::from([-1, 0, 1]);
+/// ```
+///
 /// Since `VecDeque` is a ring buffer, its elements are not necessarily contiguous
 /// in memory. If you want to access the elements as a single slice, such as for
 /// efficient sorting, you can use [`make_contiguous`]. It rotates the `VecDeque`
@@ -2855,3 +2863,17 @@ fn from(mut other: VecDeque<T>) -> Self {
         }
     }
 }
+
+#[stable(feature = "std_collections_from_array", since = "1.55.0")]
+impl<T, const N: usize> From<[T; N]> for VecDeque<T> {
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let deq1 = VecDeque::from([1, 2, 3, 4]);
+    /// let deq2: VecDeque<_> = [1, 2, 3, 4].into();
+    /// assert_eq!(deq1, deq2);
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        core::array::IntoIter::new(arr).collect()
+    }
+}
index 91c3b16deee77194c922086dd07dbaef2b5f0fcc..617c76a680b9fa5fd3386511ddcc3fa61e0c450b 100644 (file)
 /// assert_eq!(vec, [7, 1, 2, 3]);
 /// ```
 ///
-/// The [`vec!`] macro is provided to make initialization more convenient:
+/// The [`vec!`] macro is provided for convenient initialization:
 ///
 /// ```
-/// let mut vec = vec![1, 2, 3];
-/// vec.push(4);
-/// assert_eq!(vec, [1, 2, 3, 4]);
+/// let mut vec1 = vec![1, 2, 3];
+/// vec1.push(4);
+/// let vec2 = Vec::from([1, 2, 3, 4]);
+/// assert_eq!(vec1, vec2);
 /// ```
 ///
 /// It can also initialize each element of a `Vec<T>` with a given value.
index 3dcc5cd2b5911f1651734d7ab923b33419983b9c..fdc64850f714f1141c14b30ac89713202fda85f7 100644 (file)
 /// }
 /// ```
 ///
-/// `HashMap` also implements an [`Entry API`](#method.entry), which allows
-/// for more complex methods of getting, setting, updating and removing keys and
+/// A `HashMap` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let solar_distance = HashMap::from([
+///     ("Mercury", 0.4),
+///     ("Venus", 0.7),
+///     ("Earth", 1.0),
+///     ("Mars", 1.5),
+/// ]);
+/// ```
+///
+/// `HashMap` implements an [`Entry API`](#method.entry), which allows
+/// for complex methods of getting, setting, updating and removing keys and
 /// their values:
 ///
 /// ```
 /// }
 ///
 /// // Use a HashMap to store the vikings' health points.
-/// let mut vikings = HashMap::new();
-///
-/// vikings.insert(Viking::new("Einar", "Norway"), 25);
-/// vikings.insert(Viking::new("Olaf", "Denmark"), 24);
-/// vikings.insert(Viking::new("Harald", "Iceland"), 12);
+/// let vikings = HashMap::from([
+///     (Viking::new("Einar", "Norway"), 25),
+///     (Viking::new("Olaf", "Denmark"), 24),
+///     (Viking::new("Harald", "Iceland"), 12),
+/// ]);
 ///
 /// // Use derived implementation to print the status of the vikings.
 /// for (viking, health) in &vikings {
 ///     println!("{:?} has {} hp", viking, health);
 /// }
 /// ```
-///
-/// A `HashMap` with fixed list of elements can be initialized from an array:
-///
-/// ```
-/// use std::collections::HashMap;
-///
-/// let timber_resources: HashMap<&str, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)]
-///     .iter().cloned().collect();
-/// // use the values stored in map
-/// ```
 
 #[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1151,6 +1154,37 @@ fn index(&self, key: &Q) -> &V {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.55.0")]
+// Note: as what is currently the most convenient built-in way to construct
+// a HashMap, a simple usage of this function must not *require* the user
+// to provide a type annotation in order to infer the third type parameter
+// (the hasher parameter, conventionally "S").
+// To that end, this impl is defined using RandomState as the concrete
+// type of S, rather than being generic over `S: BuildHasher + Default`.
+// It is expected that users who want to specify a hasher will manually use
+// `with_capacity_and_hasher`.
+// If type parameter defaults worked on impls, and if type parameter
+// defaults could be mixed with const generics, then perhaps
+// this could be generalized.
+// See also the equivalent impl on HashSet.
+impl<K, V, const N: usize> From<[(K, V); N]> for HashMap<K, V, RandomState>
+where
+    K: Eq + Hash,
+{
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let map1 = HashMap::from([(1, 2), (3, 4)]);
+    /// let map2: HashMap<_, _> = [(1, 2), (3, 4)].into();
+    /// assert_eq!(map1, map2);
+    /// ```
+    fn from(arr: [(K, V); N]) -> Self {
+        crate::array::IntoIter::new(arr).collect()
+    }
+}
+
 /// An iterator over the entries of a `HashMap`.
 ///
 /// This `struct` is created by the [`iter`] method on [`HashMap`]. See its
index 819be14222752e1eb5724713361f22e504d90798..def085e380b19953dfbb86d830f3a9591e438167 100644 (file)
@@ -1085,3 +1085,15 @@ fn drop(&mut self) {
         assert_eq!(map.len(), 2);
     }
 }
+
+#[test]
+fn from_array() {
+    let map = HashMap::from([(1, 2), (3, 4)]);
+    let unordered_duplicates = HashMap::from([(3, 4), (1, 2), (1, 2)]);
+    assert_eq!(map, unordered_duplicates);
+
+    // This next line must infer the hasher type parameter.
+    // If you make a change that causes this line to no longer infer,
+    // that's a problem!
+    let _must_not_require_type_annotation = HashMap::from([(1, 2)]);
+}
index 8c801b9f1285db193e8af703a92e155ca5ae3b33..6e58ebdce507d07f97fb3f8d2e417dd2a83bb6eb 100644 (file)
 /// }
 /// ```
 ///
-/// A `HashSet` with fixed list of elements can be initialized from an array:
+/// A `HashSet` with a known list of items can be initialized from an array:
 ///
 /// ```
 /// use std::collections::HashSet;
 ///
-/// let viking_names: HashSet<&'static str> =
-///     [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
-/// // use the values stored in the set
+/// let viking_names = HashSet::from(["Einar", "Olaf", "Harald"]);
 /// ```
 ///
 /// [hash set]: crate::collections#use-the-set-variant-of-any-of-these-maps-when
@@ -998,6 +996,37 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> HashSet<T, S> {
     }
 }
 
+#[stable(feature = "std_collections_from_array", since = "1.55.0")]
+// Note: as what is currently the most convenient built-in way to construct
+// a HashSet, a simple usage of this function must not *require* the user
+// to provide a type annotation in order to infer the third type parameter
+// (the hasher parameter, conventionally "S").
+// To that end, this impl is defined using RandomState as the concrete
+// type of S, rather than being generic over `S: BuildHasher + Default`.
+// It is expected that users who want to specify a hasher will manually use
+// `with_capacity_and_hasher`.
+// If type parameter defaults worked on impls, and if type parameter
+// defaults could be mixed with const generics, then perhaps
+// this could be generalized.
+// See also the equivalent impl on HashMap.
+impl<T, const N: usize> From<[T; N]> for HashSet<T, RandomState>
+where
+    T: Eq + Hash,
+{
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    ///
+    /// let set1 = HashSet::from([1, 2, 3, 4]);
+    /// let set2: HashSet<_> = [1, 2, 3, 4].into();
+    /// assert_eq!(set1, set2);
+    /// ```
+    fn from(arr: [T; N]) -> Self {
+        crate::array::IntoIter::new(arr).collect()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Extend<T> for HashSet<T, S>
 where
index 40f8467fd93fddf18907d1a9d55440164a9a522f..6a625e6243c2157f4416502f28b3240b56480e3b 100644 (file)
@@ -484,3 +484,15 @@ fn drop(&mut self) {
     assert_eq!(DROPS.load(Ordering::SeqCst), 3);
     assert_eq!(set.len(), 0);
 }
+
+#[test]
+fn from_array() {
+    let set = HashSet::from([1, 2, 3, 4]);
+    let unordered_duplicates = HashSet::from([4, 1, 4, 3, 2]);
+    assert_eq!(set, unordered_duplicates);
+
+    // This next line must infer the hasher type parameter.
+    // If you make a change that causes this line to no longer infer,
+    // that's a problem!
+    let _must_not_require_type_annotation = HashSet::from([1, 2]);
+}