From 870b7cbb11d799bcabc6eb5a919a27821c981bc1 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 18 May 2020 20:06:00 +0200 Subject: [PATCH 1/7] improve chunks + windows err on size 0 --- library/core/src/slice/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 9ed5a1f962215..77fe379feeebe 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -680,7 +680,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn windows(&self, size: usize) -> Windows<'_, T> { - assert!(size != 0); + assert_ne!(size, 0); Windows { v: self, size } } @@ -714,7 +714,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { - assert!(chunk_size != 0); + assert_ne!(chunk_size, 0); Chunks { v: self, chunk_size } } @@ -752,7 +752,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { - assert!(chunk_size != 0); + assert_ne!(chunk_size, 0); ChunksMut { v: self, chunk_size } } @@ -789,7 +789,7 @@ impl [T] { #[stable(feature = "chunks_exact", since = "1.31.0")] #[inline] pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> { - assert!(chunk_size != 0); + assert_ne!(chunk_size, 0); let rem = self.len() % chunk_size; let len = self.len() - rem; let (fst, snd) = self.split_at(len); @@ -834,7 +834,7 @@ impl [T] { #[stable(feature = "chunks_exact", since = "1.31.0")] #[inline] pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> { - assert!(chunk_size != 0); + assert_ne!(chunk_size, 0); let rem = self.len() % chunk_size; let len = self.len() - rem; let (fst, snd) = self.split_at_mut(len); From d405347f095a20d832261bbf777c8214d7e61dc9 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 18 May 2020 20:40:37 +0200 Subject: [PATCH 2/7] adds `slice::array_chunks` --- library/core/src/slice/mod.rs | 180 ++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 77fe379feeebe..a7d24492facd1 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -841,6 +841,41 @@ impl [T] { ChunksExactMut { v: fst, rem: snd, chunk_size } } + /// Returns an iterator over `N` elements of the slice at a time, starting at the + /// beginning of the slice. + /// + /// The chunks are slices and do not overlap. If `N` does not divide the length of the + /// slice, then the last up to `N-1` elements will be omitted and can be retrieved + /// from the `remainder` function of the iterator. + /// + /// # Panics + /// + /// Panics if `N` is 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_chunks)] + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.array_chunks(); + /// assert_eq!(iter.next().unwrap(), &['l', 'o']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e']); + /// assert!(iter.next().is_none()); + /// assert_eq!(iter.remainder(), &['m']); + /// ``` + /// + /// [`chunks`]: #method.chunks + /// [`rchunks_exact`]: #method.rchunks_exact + #[unstable(feature = "array_chunks", issue = "none")] + #[inline] + pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { + assert_ne!(N, 0); + let rem = self.len() % N; + let len = self.len() - rem; + let (fst, snd) = self.split_at(len); + ArrayChunks { v: fst, rem: snd } + } + /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end /// of the slice. /// @@ -5432,6 +5467,151 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> { } } +/// An iterator over a slice in (non-overlapping) chunks (`N` elements at a +/// time), starting at the beginning of the slice. +/// +/// When the slice len is not evenly divided by the chunk size, the last +/// up to `chunk_size-1` elements will be omitted but can be retrieved from +/// the [`remainder`] function from the iterator. +/// +/// This struct is created by the [`array_chunks`] method on [slices]. +/// +/// [`array_chunks`]: ../../std/primitive.slice.html#method.array_chunks +/// [`remainder`]: ../../std/slice/struct.ArrayChunks.html#method.remainder +/// [slices]: ../../std/primitive.slice.html +#[derive(Debug)] +#[unstable(feature = "array_chunks", issue = "none")] +pub struct ArrayChunks<'a, T: 'a, const N: usize> { + v: &'a [T], + rem: &'a [T], +} + +impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { + /// Returns the remainder of the original slice that is not going to be + /// returned by the iterator. The returned slice has at most `chunk_size-1` + /// elements. + #[unstable(feature = "array_chunks", issue = "none")] + pub fn remainder(&self) -> &'a [T] { + self.rem + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[unstable(feature = "array_chunks", issue = "none")] +impl Clone for ArrayChunks<'_, T, N> { + fn clone(&self) -> Self { + ArrayChunks { v: self.v, rem: self.rem } + } +} + +#[unstable(feature = "array_chunks", issue = "none")] +impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { + type Item = &'a [T; N]; + + #[inline] + fn next(&mut self) -> Option<&'a [T; N]> { + if self.v.len() < N { + None + } else { + let (fst, snd) = self.v.split_at(N); + self.v = snd; + // SAFETY: This is safe as fst is exactly N elements long. + let ptr = fst.as_ptr() as *const [T; N]; + unsafe { Some(&*ptr) } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let n = self.v.len() / N; + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let (start, overflow) = n.overflowing_mul(N); + if start >= self.v.len() || overflow { + self.v = &[]; + None + } else { + let (_, snd) = self.v.split_at(start); + self.v = snd; + self.next() + } + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[unstable(feature = "array_chunks", issue = "none")] +impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T; N]> { + if self.v.len() < N { + None + } else { + let (fst, snd) = self.v.split_at(self.v.len() - N); + self.v = fst; + // SAFETY: This is safe as snd is exactly N elements long. + let ptr = snd.as_ptr() as *const [T; N]; + unsafe { Some(&*ptr) } + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + let start = (len - 1 - n) * N; + let end = start + N; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + // SAFETY: This is safe as snd is exactly N elements long. + let ptr = nth_back.as_ptr() as *const [T; N]; + unsafe { Some(&*ptr) } + } + } +} + +#[unstable(feature = "array_chunks", issue = "none")] +impl ExactSizeIterator for ArrayChunks<'_, T, N> { + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ArrayChunks<'_, T, N> {} + +#[unstable(feature = "array_chunks", issue = "none")] +impl FusedIterator for ArrayChunks<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "array_chunks", issue = "none")] +unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> { + unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T; N] { + let start = i * N; + // SAFETY: This is safe as `i` must be less than `self.size_hint`. + let segment = unsafe { from_raw_parts(self.v.as_ptr().add(start), N) }; + // SAFETY: This is safe as segment is exactly `N` elements long. + unsafe { &*(segment.as_ptr() as *const [T; N]) } + } + fn may_have_side_effect() -> bool { + false + } +} + /// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a /// time), starting at the end of the slice. /// From d27007fd6d41a8e9f16228d036c1fedaf0449efd Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 18 May 2020 21:24:37 +0200 Subject: [PATCH 3/7] add tests for array_chunks --- library/core/src/slice/mod.rs | 1 - library/core/tests/lib.rs | 1 + library/core/tests/slice.rs | 91 +++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index a7d24492facd1..e33dad38d4b0d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -865,7 +865,6 @@ impl [T] { /// ``` /// /// [`chunks`]: #method.chunks - /// [`rchunks_exact`]: #method.rchunks_exact #[unstable(feature = "array_chunks", issue = "none")] #[inline] pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 47ed6db6c677b..6b28a815f033a 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,4 +1,5 @@ #![feature(alloc_layout_extra)] +#![feature(array_chunks)] #![feature(bool_to_option)] #![feature(bound_cloned)] #![feature(box_syntax)] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 8e240832c13b8..27cc7fce1daa3 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -473,6 +473,97 @@ fn test_chunks_exact_mut_zip() { assert_eq!(v1, [13, 14, 19, 20, 4]); } +#[test] +fn test_array_chunks_infer() { + let v: &[i32] = &[0, 1, 2, 3, 4, -4]; + let c = v.array_chunks(); + for &[a, b, c] in c { + assert_eq!(a + b + c, 3); + } + + let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6]; + let total = v2.array_chunks().map(|&[a, b]| a * b).sum::(); + assert_eq!(total, 2 * 3 + 4 * 5); +} + +#[test] +fn test_array_chunks_count() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let c = v.array_chunks::<3>(); + assert_eq!(c.count(), 2); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let c2 = v2.array_chunks::<2>(); + assert_eq!(c2.count(), 2); + + let v3: &[i32] = &[]; + let c3 = v3.array_chunks::<2>(); + assert_eq!(c3.count(), 0); +} + +#[test] +fn test_array_chunks_nth() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.array_chunks::<2>(); + assert_eq!(c.nth(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6]; + let mut c2 = v2.array_chunks::<3>(); + assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]); + assert_eq!(c2.next(), None); +} + +#[test] +fn test_array_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.array_chunks::<2>(); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.array_chunks::<3>(); + assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]); + assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.array_chunks::<10>(); + assert_eq!(c3.nth_back(0), None); +} + +#[test] +fn test_array_chunks_last() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let c = v.array_chunks::<2>(); + assert_eq!(c.last().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let c2 = v2.array_chunks::<2>(); + assert_eq!(c2.last().unwrap(), &[2, 3]); +} + +#[test] +fn test_array_chunks_remainder() { + let v: &[i32] = &[0, 1, 2, 3, 4]; + let c = v.array_chunks::<2>(); + assert_eq!(c.remainder(), &[4]); +} + +#[test] +fn test_array_chunks_zip() { + let v1: &[i32] = &[0, 1, 2, 3, 4]; + let v2: &[i32] = &[6, 7, 8, 9, 10]; + + let res = v1 + .array_chunks::<2>() + .zip(v2.array_chunks::<2>()) + .map(|(a, b)| a.iter().sum::() + b.iter().sum::()) + .collect::>(); + assert_eq!(res, vec![14, 22]); +} + #[test] fn test_rchunks_count() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From 95fa63e63f21ba3270870920d67836016b4c9711 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 18 May 2020 23:14:55 +0200 Subject: [PATCH 4/7] liballoc export ArrayChunks --- library/alloc/src/lib.rs | 1 + library/alloc/src/slice.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 90e2d2531c552..fe91cceed697a 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -76,6 +76,7 @@ #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(test))] #![feature(allocator_api)] +#![feature(array_chunks)] #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] #![feature(box_patterns)] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 3d51115fe01d3..0bb64d6bb6f02 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -95,6 +95,8 @@ use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; +#[unstable(feature = "array_chunks", issue = "none")] +pub use core::slice::ArrayChunks; #[stable(feature = "slice_get_slice", since = "1.28.0")] pub use core::slice::SliceIndex; #[stable(feature = "from_ref", since = "1.28.0")] From a410ebc5ea44c0cea23a8e6d05aab2fe66b17203 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 20 Jul 2020 23:33:22 +0200 Subject: [PATCH 5/7] add note to array_chunks --- library/core/src/slice/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e33dad38d4b0d..fdf3c7b3f637e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -848,6 +848,8 @@ impl [T] { /// slice, then the last up to `N-1` elements will be omitted and can be retrieved /// from the `remainder` function of the iterator. /// + /// This method is the const generic equivalent of [`chunks_exact`]. + /// /// # Panics /// /// Panics if `N` is 0. @@ -864,7 +866,7 @@ impl [T] { /// assert_eq!(iter.remainder(), &['m']); /// ``` /// - /// [`chunks`]: #method.chunks + /// [`chunks_exact`]: #method.chunks_exact #[unstable(feature = "array_chunks", issue = "none")] #[inline] pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { From e75ffb0f1c566e11011b72ac04c3afcad3bf2b13 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 31 Jul 2020 08:24:39 +0200 Subject: [PATCH 6/7] use Iter<'_, [T; N]> in array_chunks --- library/core/src/slice/mod.rs | 78 +++++++++-------------------------- 1 file changed, 20 insertions(+), 58 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index fdf3c7b3f637e..d2d42d4be4b57 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -852,7 +852,8 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. + /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// error before this method gets stabilized. /// /// # Examples /// @@ -871,10 +872,12 @@ impl [T] { #[inline] pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { assert_ne!(N, 0); - let rem = self.len() % N; - let len = self.len() - rem; - let (fst, snd) = self.split_at(len); - ArrayChunks { v: fst, rem: snd } + let len = self.len() / N; + let (fst, snd) = self.split_at(len * N); + // SAFETY: We cast a slice of `len * N` elements into + // a slice of `len` many `N` elements chunks. + let array_slice: &[[T; N]] = unsafe { from_raw_parts(fst.as_ptr().cast(), len) }; + ArrayChunks { iter: array_slice.iter(), rem: snd } } /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end @@ -5483,7 +5486,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> { #[derive(Debug)] #[unstable(feature = "array_chunks", issue = "none")] pub struct ArrayChunks<'a, T: 'a, const N: usize> { - v: &'a [T], + iter: Iter<'a, [T; N]>, rem: &'a [T], } @@ -5501,7 +5504,7 @@ impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { #[unstable(feature = "array_chunks", issue = "none")] impl Clone for ArrayChunks<'_, T, N> { fn clone(&self) -> Self { - ArrayChunks { v: self.v, rem: self.rem } + ArrayChunks { iter: self.iter.clone(), rem: self.rem } } } @@ -5511,44 +5514,27 @@ impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { #[inline] fn next(&mut self) -> Option<&'a [T; N]> { - if self.v.len() < N { - None - } else { - let (fst, snd) = self.v.split_at(N); - self.v = snd; - // SAFETY: This is safe as fst is exactly N elements long. - let ptr = fst.as_ptr() as *const [T; N]; - unsafe { Some(&*ptr) } - } + self.iter.next() } #[inline] fn size_hint(&self) -> (usize, Option) { - let n = self.v.len() / N; - (n, Some(n)) + self.iter.size_hint() } #[inline] fn count(self) -> usize { - self.len() + self.iter.count() } #[inline] fn nth(&mut self, n: usize) -> Option { - let (start, overflow) = n.overflowing_mul(N); - if start >= self.v.len() || overflow { - self.v = &[]; - None - } else { - let (_, snd) = self.v.split_at(start); - self.v = snd; - self.next() - } + self.iter.nth(n) } #[inline] - fn last(mut self) -> Option { - self.next_back() + fn last(self) -> Option { + self.iter.last() } } @@ -5556,39 +5542,19 @@ impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> { #[inline] fn next_back(&mut self) -> Option<&'a [T; N]> { - if self.v.len() < N { - None - } else { - let (fst, snd) = self.v.split_at(self.v.len() - N); - self.v = fst; - // SAFETY: This is safe as snd is exactly N elements long. - let ptr = snd.as_ptr() as *const [T; N]; - unsafe { Some(&*ptr) } - } + self.iter.next_back() } #[inline] fn nth_back(&mut self, n: usize) -> Option { - let len = self.len(); - if n >= len { - self.v = &[]; - None - } else { - let start = (len - 1 - n) * N; - let end = start + N; - let nth_back = &self.v[start..end]; - self.v = &self.v[..start]; - // SAFETY: This is safe as snd is exactly N elements long. - let ptr = nth_back.as_ptr() as *const [T; N]; - unsafe { Some(&*ptr) } - } + self.iter.nth_back(n) } } #[unstable(feature = "array_chunks", issue = "none")] impl ExactSizeIterator for ArrayChunks<'_, T, N> { fn is_empty(&self) -> bool { - self.v.is_empty() + self.iter.is_empty() } } @@ -5602,11 +5568,7 @@ impl FusedIterator for ArrayChunks<'_, T, N> {} #[unstable(feature = "array_chunks", issue = "none")] unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T; N] { - let start = i * N; - // SAFETY: This is safe as `i` must be less than `self.size_hint`. - let segment = unsafe { from_raw_parts(self.v.as_ptr().add(start), N) }; - // SAFETY: This is safe as segment is exactly `N` elements long. - unsafe { &*(segment.as_ptr() as *const [T; N]) } + unsafe { self.iter.get_unchecked(i) } } fn may_have_side_effect() -> bool { false From d51b71a35a816f4be56f77d1d1a6f4095352649e Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 1 Aug 2020 07:49:24 +0200 Subject: [PATCH 7/7] add tracking issue --- library/alloc/src/slice.rs | 2 +- library/core/src/slice/mod.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 0bb64d6bb6f02..b791c775548cd 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -95,7 +95,7 @@ use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] pub use core::slice::ArrayChunks; #[stable(feature = "slice_get_slice", since = "1.28.0")] pub use core::slice::SliceIndex; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d2d42d4be4b57..93608a1ce4864 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -868,7 +868,7 @@ impl [T] { /// ``` /// /// [`chunks_exact`]: #method.chunks_exact - #[unstable(feature = "array_chunks", issue = "none")] + #[unstable(feature = "array_chunks", issue = "74985")] #[inline] pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { assert_ne!(N, 0); @@ -5484,7 +5484,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> { /// [`remainder`]: ../../std/slice/struct.ArrayChunks.html#method.remainder /// [slices]: ../../std/primitive.slice.html #[derive(Debug)] -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] pub struct ArrayChunks<'a, T: 'a, const N: usize> { iter: Iter<'a, [T; N]>, rem: &'a [T], @@ -5494,21 +5494,21 @@ impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { /// Returns the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. - #[unstable(feature = "array_chunks", issue = "none")] + #[unstable(feature = "array_chunks", issue = "74985")] pub fn remainder(&self) -> &'a [T] { self.rem } } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] impl Clone for ArrayChunks<'_, T, N> { fn clone(&self) -> Self { ArrayChunks { iter: self.iter.clone(), rem: self.rem } } } -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { type Item = &'a [T; N]; @@ -5538,7 +5538,7 @@ impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { } } -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> { #[inline] fn next_back(&mut self) -> Option<&'a [T; N]> { @@ -5551,7 +5551,7 @@ impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> { } } -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] impl ExactSizeIterator for ArrayChunks<'_, T, N> { fn is_empty(&self) -> bool { self.iter.is_empty() @@ -5561,11 +5561,11 @@ impl ExactSizeIterator for ArrayChunks<'_, T, N> { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for ArrayChunks<'_, T, N> {} -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] impl FusedIterator for ArrayChunks<'_, T, N> {} #[doc(hidden)] -#[unstable(feature = "array_chunks", issue = "none")] +#[unstable(feature = "array_chunks", issue = "74985")] unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T; N] { unsafe { self.iter.get_unchecked(i) }