From a891f6edfeb4d7b061a215ba160fca0e4804ffd2 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 10:16:29 +0100 Subject: Introduce the GroupBy and GroupByMut Iterators --- library/alloc/src/lib.rs | 1 + library/alloc/src/slice.rs | 2 ++ library/alloc/tests/lib.rs | 1 + library/alloc/tests/slice.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 31 insertions(+) (limited to 'library/alloc') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3ac34c9ae28..34102d9c403 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -140,6 +140,7 @@ #![feature(try_trait)] #![feature(type_alias_impl_trait)] #![feature(associated_type_bounds)] +#![feature(slice_group_by)] // Allow testing this library #[cfg(test)] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 064700fc72c..bfa317ffd73 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -118,6 +118,8 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; +#[unstable(feature = "slice_group_by", issue = "0")] +pub use core::slice::{GroupBy, GroupByMut}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index b7cc03f8eb9..268153242c7 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -21,6 +21,7 @@ #![feature(iter_map_while)] #![feature(int_bits_const)] #![feature(vecdeque_binary_search)] +#![feature(slice_group_by)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index a4f0fb415fb..e2fdb5a6b5a 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -1898,3 +1898,30 @@ fn subslice_patterns() { m!(&mut v, [..] => ()); m!(&mut v, [x, .., y] => c!((x, y), (&mut N, &mut N), (&mut N(0), &mut N(4)))); } + +#[test] +fn test_group_by() { + let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; + + let mut iter = slice.group_by(|a, b| a == b); + + assert_eq!(iter.next(), Some(&[1, 1, 1][..])); + + assert_eq!(iter.remaining(), &[3, 3, 2, 2, 2]); + + assert_eq!(iter.next(), Some(&[3, 3][..])); + assert_eq!(iter.next(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next(), None); +} + +#[test] +fn test_group_by_rev() { + let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; + + let mut iter = slice.group_by(|a, b| a == b); + + assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next_back(), Some(&[3, 3][..])); + assert_eq!(iter.next_back(), Some(&[1, 1, 1][..])); + assert_eq!(iter.next_back(), None); +} -- cgit 1.4.1-3-g733a5 From 1c55a73b750bcae1bbf05cbafbd36bce8bd993fa Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 11:17:41 +0100 Subject: Implement it with only safe code --- library/alloc/tests/slice.rs | 39 +++++-- library/core/src/slice/iter.rs | 238 +++++++++++++++++------------------------ library/core/src/slice/mod.rs | 14 +-- 3 files changed, 128 insertions(+), 163 deletions(-) (limited to 'library/alloc') diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index e2fdb5a6b5a..8f03a9240e2 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -1904,24 +1904,43 @@ fn test_group_by() { let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; let mut iter = slice.group_by(|a, b| a == b); - assert_eq!(iter.next(), Some(&[1, 1, 1][..])); - - assert_eq!(iter.remaining(), &[3, 3, 2, 2, 2]); - assert_eq!(iter.next(), Some(&[3, 3][..])); assert_eq!(iter.next(), Some(&[2, 2, 2][..])); assert_eq!(iter.next(), None); -} - -#[test] -fn test_group_by_rev() { - let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; let mut iter = slice.group_by(|a, b| a == b); - assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); assert_eq!(iter.next_back(), Some(&[3, 3][..])); assert_eq!(iter.next_back(), Some(&[1, 1, 1][..])); assert_eq!(iter.next_back(), None); + + let mut iter = slice.group_by(|a, b| a == b); + assert_eq!(iter.next(), Some(&[1, 1, 1][..])); + assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next(), Some(&[3, 3][..])); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn test_group_by_mut() { + let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2]; + + let mut iter = slice.group_by_mut(|a, b| a == b); + assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); + assert_eq!(iter.next(), Some(&mut [3, 3][..])); + assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next(), None); + + let mut iter = slice.group_by_mut(|a, b| a == b); + assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next_back(), Some(&mut [3, 3][..])); + assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..])); + assert_eq!(iter.next_back(), None); + + let mut iter = slice.group_by_mut(|a, b| a == b); + assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); + assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next(), Some(&mut [3, 3][..])); + assert_eq!(iter.next_back(), None); } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 917997f902a..8f52fa852ba 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2968,127 +2968,6 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { } } -macro_rules! group_by { - (struct $name:ident, $elem:ty, $mkslice:ident) => { - #[unstable(feature = "slice_group_by", issue = "0")] - impl<'a, T: 'a, P> $name<'a, T, P> { - #[inline] - fn is_empty(&self) -> bool { - self.ptr == self.end - } - - #[inline] - fn remaining_len(&self) -> usize { - unsafe { self.end.offset_from(self.ptr) as usize } - } - } - - #[unstable(feature = "slice_group_by", issue = "0")] - impl<'a, T: 'a, P> Iterator for $name<'a, T, P> - where P: FnMut(&T, &T) -> bool, - { - type Item = $elem; - - fn next(&mut self) -> Option { - // we use an unsafe block to avoid bounds checking here. - // this is safe because the only thing we do here is to get - // two elements at `ptr` and `ptr + 1`, bounds checking is done by hand. - unsafe { - if self.is_empty() { return None } - - let mut i = 0; - let mut ptr = self.ptr; - - // we need to get *two* contiguous elements so we check that: - // - the first element is at the `end - 1` position because - // - the second one will be read from `ptr + 1` that must - // be lower or equal to `end` - while ptr != self.end.sub(1) { - let a = &*ptr; - ptr = ptr.add(1); - let b = &*ptr; - - i += 1; - - if !(self.predicate)(a, b) { - let slice = $mkslice(self.ptr, i); - self.ptr = ptr; - return Some(slice) - } - } - - // `i` is either `0` or the slice `length - 1` because either: - // - we have not entered the loop and so `i` is equal to `0` - // the slice length is necessarily `1` because we ensure it is not empty - // - we have entered the loop and we have not early returned - // so `i` is equal to the slice `length - 1` - let slice = $mkslice(self.ptr, i + 1); - self.ptr = self.end; - Some(slice) - } - } - - fn size_hint(&self) -> (usize, Option) { - if self.is_empty() { return (0, Some(0)) } - let len = self.remaining_len(); - (1, Some(len)) - } - - fn last(mut self) -> Option { - self.next_back() - } - } - - #[unstable(feature = "slice_group_by", issue = "0")] - impl<'a, T: 'a, P> DoubleEndedIterator for $name<'a, T, P> - where P: FnMut(&T, &T) -> bool, - { - fn next_back(&mut self) -> Option { - // during the loop we retrieve two elements at `ptr` and `ptr - 1`. - unsafe { - if self.is_empty() { return None } - - let mut i = 0; - // we ensure that the first element that will be read - // is not under `end` because `end` is out of bound. - let mut ptr = self.end.sub(1); - - while ptr != self.ptr { - // we first get `a` that is at the left of `ptr` - // then `b` that is under the `ptr` position. - let a = &*ptr.sub(1); - let b = &*ptr; - - i += 1; - - if !(self.predicate)(a, b) { - // the slice to return starts at the `ptr` position - // and `i` is the length of it. - let slice = $mkslice(ptr, i); - - // because `end` is always an invalid bound - // we use `ptr` as `end` for the future call to `next`. - self.end = ptr; - return Some(slice) - } - - ptr = ptr.sub(1); - } - - let slice = $mkslice(self.ptr, i + 1); - self.ptr = self.end; - Some(slice) - } - } - } - - #[unstable(feature = "slice_group_by", issue = "0")] - impl<'a, T: 'a, P> FusedIterator for $name<'a, T, P> - where P: FnMut(&T, &T) -> bool, - { } - } -} - /// An iterator over slice in (non-overlapping) chunks separated by a predicate. /// /// This struct is created by the [`group_by`] method on [slices]. @@ -3098,25 +2977,65 @@ macro_rules! group_by { #[unstable(feature = "slice_group_by", issue = "0")] #[derive(Debug)] // FIXME implement Debug to be more user friendly pub struct GroupBy<'a, T: 'a, P> { - ptr: *const T, - end: *const T, + slice: &'a [T], predicate: P, - _phantom: marker::PhantomData<&'a T>, } #[unstable(feature = "slice_group_by", issue = "0")] -impl<'a, T: 'a, P> GroupBy<'a, T, P> +impl<'a, T: 'a, P> GroupBy<'a, T, P> { + pub(super) fn new(slice: &'a [T], predicate: P) -> Self { + GroupBy { slice, predicate } + } +} + +#[unstable(feature = "slice_group_by", issue = "0")] +impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { - /// Returns the remainder of the original slice that is going to be - /// returned by the iterator. - pub fn remaining(&self) -> &[T] { - let len = self.remaining_len(); - unsafe { from_raw_parts(self.ptr, len) } + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let (head, tail) = self.slice.split_at(len); + self.slice = tail; + Some(head) + } } } -group_by!{ struct GroupBy, &'a [T], from_raw_parts } +#[unstable(feature = "slice_group_by", issue = "0")] +impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> +where P: FnMut(&T, &T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next_back() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let (head, tail) = self.slice.split_at(self.slice.len() - len); + self.slice = head; + Some(tail) + } + } +} + +#[unstable(feature = "slice_group_by", issue = "0")] +impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> +where P: FnMut(&T, &T) -> bool, +{ } /// An iterator over slice in (non-overlapping) mutable chunks separated /// by a predicate. @@ -3128,22 +3047,59 @@ group_by!{ struct GroupBy, &'a [T], from_raw_parts } #[unstable(feature = "slice_group_by", issue = "0")] #[derive(Debug)] // FIXME implement Debug to be more user friendly pub struct GroupByMut<'a, T: 'a, P> { - ptr: *mut T, - end: *mut T, + slice: &'a mut [T], predicate: P, - _phantom: marker::PhantomData<&'a T>, } #[unstable(feature = "slice_group_by", issue = "0")] -impl<'a, T: 'a, P> GroupByMut<'a, T, P> +impl<'a, T: 'a, P> GroupByMut<'a, T, P> { + pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { + GroupByMut { slice, predicate } + } +} + +#[unstable(feature = "slice_group_by", issue = "0")] +impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, { - /// Returns the remainder of the original slice that is going to be - /// returned by the iterator. - pub fn into_remaining(self) -> &'a mut [T] { - let len = self.remaining_len(); - unsafe { from_raw_parts_mut(self.ptr, len) } + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let slice = mem::take(&mut self.slice); + let (head, tail) = slice.split_at_mut(len); + self.slice = tail; + Some(head) + } } } -group_by!{ struct GroupByMut, &'a mut [T], from_raw_parts_mut } +#[unstable(feature = "slice_group_by", issue = "0")] +impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> +where P: FnMut(&T, &T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option { + if self.slice.is_empty() { + None + } else { + let mut len = 1; + let mut iter = self.slice.windows(2); + while let Some([l, r]) = iter.next_back() { + if (self.predicate)(l, r) { len += 1 } else { break } + } + let slice = mem::take(&mut self.slice); + let (head, tail) = slice.split_at_mut(slice.len() - len); + self.slice = head; + Some(tail) + } + } +} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e366baa34c6..2e304cc5d2e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1233,12 +1233,7 @@ impl [T] { pub fn group_by(&self, pred: F) -> GroupBy where F: FnMut(&T, &T) -> bool { - GroupBy { - ptr: self.as_ptr(), - end: unsafe { self.as_ptr().add(self.len()) }, - predicate: pred, - _phantom: marker::PhantomData, - } + GroupBy::new(self, pred) } /// Returns an iterator over the slice producing non-overlapping mutable @@ -1267,12 +1262,7 @@ impl [T] { pub fn group_by_mut(&mut self, pred: F) -> GroupByMut where F: FnMut(&T, &T) -> bool { - GroupByMut { - ptr: self.as_mut_ptr(), - end: unsafe { self.as_mut_ptr().add(self.len()) }, - predicate: pred, - _phantom: marker::PhantomData, - } + GroupByMut::new(self, pred) } /// Divides one slice into two at an index. -- cgit 1.4.1-3-g733a5 From 1b406afe23c17467f43a5c1bd83b4af1d55d08d9 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 11:37:40 +0100 Subject: Use none as the issue instead of 0 --- library/alloc/src/slice.rs | 2 +- library/core/src/slice/iter.rs | 18 +++++++++--------- library/core/src/slice/mod.rs | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'library/alloc') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index bfa317ffd73..5f92dfe539f 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -118,7 +118,7 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] pub use core::slice::{GroupBy, GroupByMut}; //////////////////////////////////////////////////////////////////////////////// diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 90afd00f21d..9053376bdf2 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2974,21 +2974,21 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { /// /// [`group_by`]: ../../std/primitive.slice.html#method.group_by /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] #[derive(Debug)] // FIXME implement Debug to be more user friendly pub struct GroupBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> GroupBy<'a, T, P> { pub(super) fn new(slice: &'a [T], predicate: P) -> Self { GroupBy { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3025,7 +3025,7 @@ where P: FnMut(&T, &T) -> bool, } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3046,7 +3046,7 @@ where P: FnMut(&T, &T) -> bool, } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { } @@ -3058,21 +3058,21 @@ where P: FnMut(&T, &T) -> bool, /// /// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] #[derive(Debug)] // FIXME implement Debug to be more user friendly pub struct GroupByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> GroupByMut<'a, T, P> { pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { GroupByMut { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3110,7 +3110,7 @@ where P: FnMut(&T, &T) -> bool, } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 2e304cc5d2e..40f480fa85b 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1228,7 +1228,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&[2, 2, 2][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "0")] + #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by(&self, pred: F) -> GroupBy where F: FnMut(&T, &T) -> bool @@ -1257,7 +1257,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "0")] + #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by_mut(&mut self, pred: F) -> GroupByMut where F: FnMut(&T, &T) -> bool -- cgit 1.4.1-3-g733a5 From 9940c47885df3d6873aab9a78a7725cb41e8d957 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 13:42:31 +0100 Subject: Update the slice GroupBy/Mut test --- library/alloc/tests/slice.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'library/alloc') diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 8f03a9240e2..777c10b1bf7 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -1901,15 +1901,19 @@ fn subslice_patterns() { #[test] fn test_group_by() { - let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; + let slice = &[1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; let mut iter = slice.group_by(|a, b| a == b); assert_eq!(iter.next(), Some(&[1, 1, 1][..])); assert_eq!(iter.next(), Some(&[3, 3][..])); assert_eq!(iter.next(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next(), Some(&[1][..])); + assert_eq!(iter.next(), Some(&[0][..])); assert_eq!(iter.next(), None); let mut iter = slice.group_by(|a, b| a == b); + assert_eq!(iter.next_back(), Some(&[0][..])); + assert_eq!(iter.next_back(), Some(&[1][..])); assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); assert_eq!(iter.next_back(), Some(&[3, 3][..])); assert_eq!(iter.next_back(), Some(&[1, 1, 1][..])); @@ -1917,22 +1921,28 @@ fn test_group_by() { let mut iter = slice.group_by(|a, b| a == b); assert_eq!(iter.next(), Some(&[1, 1, 1][..])); - assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next_back(), Some(&[0][..])); assert_eq!(iter.next(), Some(&[3, 3][..])); + assert_eq!(iter.next_back(), Some(&[1][..])); + assert_eq!(iter.next(), Some(&[2, 2, 2][..])); assert_eq!(iter.next_back(), None); } #[test] fn test_group_by_mut() { - let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2]; + let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; let mut iter = slice.group_by_mut(|a, b| a == b); assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); assert_eq!(iter.next(), Some(&mut [3, 3][..])); assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next(), Some(&mut [1][..])); + assert_eq!(iter.next(), Some(&mut [0][..])); assert_eq!(iter.next(), None); let mut iter = slice.group_by_mut(|a, b| a == b); + assert_eq!(iter.next_back(), Some(&mut [0][..])); + assert_eq!(iter.next_back(), Some(&mut [1][..])); assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..])); assert_eq!(iter.next_back(), Some(&mut [3, 3][..])); assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..])); @@ -1940,7 +1950,9 @@ fn test_group_by_mut() { let mut iter = slice.group_by_mut(|a, b| a == b); assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); - assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next_back(), Some(&mut [0][..])); assert_eq!(iter.next(), Some(&mut [3, 3][..])); + assert_eq!(iter.next_back(), Some(&mut [1][..])); + assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); assert_eq!(iter.next_back(), None); } -- cgit 1.4.1-3-g733a5 From 7952ea5a04aa34dc5441a47f7d4d227193c8fdf6 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 19:10:09 +0100 Subject: Fix the fmt issues --- library/alloc/src/slice.rs | 4 ++-- library/core/src/slice/iter.rs | 31 ++++++++++++++----------------- library/core/src/slice/mod.rs | 6 ++++-- 3 files changed, 20 insertions(+), 21 deletions(-) (limited to 'library/alloc') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 5f92dfe539f..72da781da3c 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -110,6 +110,8 @@ pub use core::slice::{Chunks, Windows}; pub use core::slice::{ChunksExact, ChunksExactMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{ChunksMut, Split, SplitMut}; +#[unstable(feature = "slice_group_by", issue = "none")] +pub use core::slice::{GroupBy, GroupByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Iter, IterMut}; #[stable(feature = "rchunks", since = "1.31.0")] @@ -118,8 +120,6 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; -#[unstable(feature = "slice_group_by", issue = "none")] -pub use core::slice::{GroupBy, GroupByMut}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index a10ebacf5fb..423cbd11350 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2991,7 +2991,8 @@ impl<'a, T: 'a, P> GroupBy<'a, T, P> { #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { type Item = &'a [T]; @@ -3013,11 +3014,7 @@ where P: FnMut(&T, &T) -> bool, #[inline] fn size_hint(&self) -> (usize, Option) { - if self.slice.is_empty() { - (0, Some(0)) - } else { - (1, Some(self.slice.len())) - } + if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) } } #[inline] @@ -3028,7 +3025,8 @@ where P: FnMut(&T, &T) -> bool, #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { #[inline] fn next_back(&mut self) -> Option { @@ -3048,9 +3046,7 @@ where P: FnMut(&T, &T) -> bool, } #[unstable(feature = "slice_group_by", issue = "none")] -impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> -where P: FnMut(&T, &T) -> bool, -{ } +impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} /// An iterator over slice in (non-overlapping) mutable chunks separated /// by a predicate. @@ -3075,7 +3071,8 @@ impl<'a, T: 'a, P> GroupByMut<'a, T, P> { #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { type Item = &'a mut [T]; @@ -3098,11 +3095,7 @@ where P: FnMut(&T, &T) -> bool, #[inline] fn size_hint(&self) -> (usize, Option) { - if self.slice.is_empty() { - (0, Some(0)) - } else { - (1, Some(self.slice.len())) - } + if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) } } #[inline] @@ -3113,7 +3106,8 @@ where P: FnMut(&T, &T) -> bool, #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { #[inline] fn next_back(&mut self) -> Option { @@ -3132,3 +3126,6 @@ where P: FnMut(&T, &T) -> bool, } } } + +#[unstable(feature = "slice_group_by", issue = "none")] +impl<'a, T: 'a, P> FusedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 218cd2c25a2..648cf88b7ef 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1234,7 +1234,8 @@ impl [T] { #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by(&self, pred: F) -> GroupBy<'_, T, F> - where F: FnMut(&T, &T) -> bool + where + F: FnMut(&T, &T) -> bool, { GroupBy::new(self, pred) } @@ -1263,7 +1264,8 @@ impl [T] { #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by_mut(&mut self, pred: F) -> GroupByMut<'_, T, F> - where F: FnMut(&T, &T) -> bool + where + F: FnMut(&T, &T) -> bool, { GroupByMut::new(self, pred) } -- cgit 1.4.1-3-g733a5 From 8b53be660444d736bb6a6e1c6ba42c8180c968e7 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 31 Dec 2020 12:13:03 +0100 Subject: Replace the tracking issue for the slice_group_by feature --- library/alloc/src/slice.rs | 2 +- library/core/src/slice/iter.rs | 24 ++++++++++++------------ library/core/src/slice/mod.rs | 6 +++--- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'library/alloc') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 72da781da3c..cb015b94930 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -110,7 +110,7 @@ pub use core::slice::{Chunks, Windows}; pub use core::slice::{ChunksExact, ChunksExactMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{ChunksMut, Split, SplitMut}; -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub use core::slice::{GroupBy, GroupByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Iter, IterMut}; diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 6bb9cf99402..a367b4737db 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2975,20 +2975,20 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { /// /// [`group_by`]: ../../std/primitive.slice.html#method.group_by /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub struct GroupBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> GroupBy<'a, T, P> { pub(super) fn new(slice: &'a [T], predicate: P) -> Self { GroupBy { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3022,7 +3022,7 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3044,10 +3044,10 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GroupBy").field("slice", &self.slice).finish() @@ -3061,20 +3061,20 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> { /// /// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub struct GroupByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> GroupByMut<'a, T, P> { pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { GroupByMut { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3109,7 +3109,7 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3132,10 +3132,10 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> FusedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupByMut<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GroupByMut").field("slice", &self.slice).finish() diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b4dd057eef0..b1332a3f7bc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -57,7 +57,7 @@ pub use iter::{ArrayChunks, ArrayChunksMut}; #[unstable(feature = "array_windows", issue = "75027")] pub use iter::ArrayWindows; -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub use iter::{GroupBy, GroupByMut}; #[unstable(feature = "split_inclusive", issue = "72360")] @@ -1246,7 +1246,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&[2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "none")] + #[unstable(feature = "slice_group_by", issue = "80552")] #[inline] pub fn group_by(&self, pred: F) -> GroupBy<'_, T, F> where @@ -1291,7 +1291,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "none")] + #[unstable(feature = "slice_group_by", issue = "80552")] #[inline] pub fn group_by_mut(&mut self, pred: F) -> GroupByMut<'_, T, F> where -- cgit 1.4.1-3-g733a5