From f1eef5c2f501e89c6c1e1638d89fafd3bd51608e Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Wed, 28 Feb 2018 01:16:14 +0100 Subject: [PATCH 1/5] Add Iterator::collect_into and impl Extend for &mut Extend --- src/libcore/iter/iterator.rs | 41 ++++++++++++++++++++++++++++++++++++ src/libcore/iter/traits.rs | 12 +++++++++++ src/libcore/tests/iter.rs | 28 ++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 9d8a71250f88a..487f1c1f3f6de 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -2463,6 +2463,47 @@ pub trait Iterator { } } } + + /// Collects all items from iterator into a collection. + /// + /// This method consumes the iterator and includes all its items to the + /// passed collection. The collection is then returned, so the call chain + /// can be continued. Collections can be passed and returned either by + /// value or by mutable reference. + /// + /// This method is a counter-part of [Extend::extend](trait.Extend.html), + /// but instead of being called on collection, it's called on iterator. + /// + /// # Examples + /// Basic usage on collection passed by value + /// + /// ``` + /// let result = (3..5).collect_into(vec![1, 2]); + /// assert_eq!(vec![1, 2, 3, 4], result); + /// ``` + /// More complex usage on collection passed by mutable reference + /// + /// ``` + /// let primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]; + /// let mut vec_3 = vec![33, 53]; + /// let vec_103 = primes.into_iter() + /// .cloned() + /// .filter(|p| p % 10 == 3) + /// .collect_into(&mut vec_3) + /// .iter() + /// .map(|i| i + 100) + /// .collect::>(); + /// assert_eq!(vec![33, 53, 3, 13, 23, 43], vec_3); + /// assert_eq!(vec![133, 153, 103, 113, 123, 143], vec_103); + /// ``` + #[unstable(feature = "collect_into", issue = "0")] + fn collect_into(self, mut collection: E) -> E where + E: Extend, + Self: Sized + { + collection.extend(self); + collection + } } /// Select an element from an iterator based on the given "projection" diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 860742d9eab60..810445da7d082 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -267,6 +267,11 @@ impl IntoIterator for I { /// or, in the case of collections that permit multiple entries with equal /// keys, that entry is inserted. /// +/// When extending with items from [Iterator](trait.Iterator.html), it's often +/// more convenient to use +/// [Iterator::collect_into](trait.Iterator.html#method.collect_into). It works +/// exactly the same way, but is called on series instead of collection. +/// /// # Examples /// /// Basic usage: @@ -352,6 +357,13 @@ pub trait Extend { fn extend>(&mut self, iter: T); } +#[unstable(feature = "collect_into", issue = "0")] +impl <'a, A, E: Extend> Extend for &'a mut E { + fn extend>(&mut self, iter: T) { + (*self).extend(iter) + } +} + /// An iterator able to yield elements from both ends. /// /// Something that implements `DoubleEndedIterator` has one extra capability diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index edd75f7795ed7..b2aa288ae3d2c 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -2084,3 +2084,31 @@ fn test_monad_laws_associativity() { assert_eq!((0..10).flat_map(f).flat_map(g).sum::(), (0..10).flat_map(|x| f(x).flat_map(g)).sum::()); } + +#[test] +fn test_collect_into_passed_by_value() { + let collection = vec![1, 2]; + + let result = (3..5).collect_into(collection); + + assert_eq!(vec![1, 2, 3, 4], result); +} + +#[test] +fn test_collect_into_passed_by_mut_ref() { + let mut collection = vec![1, 2]; + + let result = (3..5).collect_into(&mut collection) as * const _; + + assert_eq!(&collection as *const _, result); + assert_eq!(vec![1, 2, 3, 4], collection); +} + +#[test] +fn test_extend_impl_for_mut_ref_extend() { + let mut collection = vec![1, 2]; + + (&mut collection).extend(3..5); + + assert_eq!(vec![1, 2, 3, 4], collection); +} From 4b4efcc8f5599f56f1997b03174a1549c5068824 Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Wed, 28 Feb 2018 01:16:14 +0100 Subject: [PATCH 2/5] Add fixed size collection example to Iterator::collect_into --- src/libcore/iter/iterator.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 487f1c1f3f6de..b1dc37eb5a956 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -2496,6 +2496,17 @@ pub trait Iterator { /// assert_eq!(vec![33, 53, 3, 13, 23, 43], vec_3); /// assert_eq!(vec![133, 153, 103, 113, 123, 143], vec_103); /// ``` + /// Collecting part of iterator into a vector with manually set capacity + /// + /// ``` + /// let mut iter = 1..5; + /// let first_2 = iter.by_ref() + /// .take(2) + /// .collect_into(Vec::with_capacity(2)); + /// let the_rest = iter.collect::>(); + /// assert_eq!(vec![1, 2], first_2); + /// assert_eq!(vec![3, 4], the_rest); + /// ``` #[unstable(feature = "collect_into", issue = "0")] fn collect_into(self, mut collection: E) -> E where E: Extend, From e0342c368da74efafc11b7671311b8f40bb328e8 Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Sun, 4 Mar 2018 02:45:10 +0100 Subject: [PATCH 3/5] Fix Iterator::collect_into tests --- src/libcore/iter/iterator.rs | 3 +++ src/libcore/tests/lib.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index b1dc37eb5a956..415641f1ad84e 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -2478,12 +2478,14 @@ pub trait Iterator { /// Basic usage on collection passed by value /// /// ``` + /// #![feature(collect_into)] /// let result = (3..5).collect_into(vec![1, 2]); /// assert_eq!(vec![1, 2, 3, 4], result); /// ``` /// More complex usage on collection passed by mutable reference /// /// ``` + /// #![feature(collect_into)] /// let primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]; /// let mut vec_3 = vec![33, 53]; /// let vec_103 = primes.into_iter() @@ -2499,6 +2501,7 @@ pub trait Iterator { /// Collecting part of iterator into a vector with manually set capacity /// /// ``` + /// #![feature(collect_into)] /// let mut iter = 1..5; /// let first_2 = iter.by_ref() /// .take(2) diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 7954d52f6b1e3..c7a29c29d1ac7 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -11,6 +11,7 @@ #![deny(warnings)] #![feature(box_syntax)] +#![feature(collect_into)] #![feature(core_float)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] From 873ed10dee34b03ea60996ef512b55254550452b Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Tue, 6 Mar 2018 22:55:59 +0100 Subject: [PATCH 4/5] Mark impl Extend for &mut Extend stable since 1.26.0 --- src/libcore/iter/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 810445da7d082..ced316be3a8f4 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -357,7 +357,7 @@ pub trait Extend { fn extend>(&mut self, iter: T); } -#[unstable(feature = "collect_into", issue = "0")] +#[stable(feature = "rust1", since = "1.26.0")] impl <'a, A, E: Extend> Extend for &'a mut E { fn extend>(&mut self, iter: T) { (*self).extend(iter) From 4a875779872fa870d9fefd3966d04359a3db34df Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Tue, 6 Mar 2018 23:29:58 +0100 Subject: [PATCH 5/5] Fix stable attribute in impl Extend for &mut Extend --- src/libcore/iter/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index ced316be3a8f4..3d1096bca78b6 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -357,7 +357,7 @@ pub trait Extend { fn extend>(&mut self, iter: T); } -#[stable(feature = "rust1", since = "1.26.0")] +#[stable(feature = "extend_impl_mut_ref", since = "1.26.0")] impl <'a, A, E: Extend> Extend for &'a mut E { fn extend>(&mut self, iter: T) { (*self).extend(iter)