diff options
Diffstat (limited to 'library/core/src/iter/adapters')
-rw-r--r-- | library/core/src/iter/adapters/array_chunks.rs | 18 | ||||
-rw-r--r-- | library/core/src/iter/adapters/by_ref_sized.rs | 19 | ||||
-rw-r--r-- | library/core/src/iter/adapters/copied.rs | 74 | ||||
-rw-r--r-- | library/core/src/iter/adapters/map_while.rs | 14 | ||||
-rw-r--r-- | library/core/src/iter/adapters/mod.rs | 10 | ||||
-rw-r--r-- | library/core/src/iter/adapters/scan.rs | 14 | ||||
-rw-r--r-- | library/core/src/iter/adapters/skip.rs | 12 | ||||
-rw-r--r-- | library/core/src/iter/adapters/take.rs | 14 | ||||
-rw-r--r-- | library/core/src/iter/adapters/take_while.rs | 14 |
9 files changed, 98 insertions, 91 deletions
diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 9b479a9f8..d4fb88610 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,6 +1,6 @@ use crate::array; use crate::iter::{ByRefSized, FusedIterator, Iterator}; -use crate::ops::{ControlFlow, NeverShortCircuit, Try}; +use crate::ops::{ControlFlow, Try}; /// An iterator over `N` elements of the iterator at a time. /// @@ -82,13 +82,7 @@ where } } - fn fold<B, F>(mut self, init: B, f: F) -> B - where - Self: Sized, - F: FnMut(B, Self::Item) -> B, - { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 - } + impl_fold_via_try_fold! { fold -> try_fold } } #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] @@ -126,13 +120,7 @@ where try { acc } } - fn rfold<B, F>(mut self, init: B, f: F) -> B - where - Self: Sized, - F: FnMut(B, Self::Item) -> B, - { - self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 - } + impl_fold_via_try_fold! { rfold -> try_rfold } } impl<I, const N: usize> ArrayChunks<I, N> diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 477e7117c..1945e402f 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,4 +1,7 @@ -use crate::ops::{NeverShortCircuit, Try}; +use crate::{ + const_closure::ConstFnMutClosure, + ops::{NeverShortCircuit, Try}, +}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -36,12 +39,13 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> { } #[inline] - fn fold<B, F>(self, init: B, f: F) -> B + fn fold<B, F>(self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `fold` needs ownership, so this can't forward directly. - I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)) + .0 } #[inline] @@ -72,12 +76,17 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> { } #[inline] - fn rfold<B, F>(self, init: B, f: F) -> B + fn rfold<B, F>(self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `rfold` needs ownership, so this can't forward directly. - I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_rfold( + self.0, + init, + ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp), + ) + .0 } #[inline] diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index f9bfd77d7..62d3afb81 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -2,7 +2,10 @@ use crate::iter::adapters::{ zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::iter::{FusedIterator, TrustedLen}; +use crate::mem::MaybeUninit; +use crate::mem::SizedTypeProperties; use crate::ops::Try; +use crate::{array, ptr}; /// An iterator that copies the elements of an underlying iterator. /// @@ -44,6 +47,15 @@ where self.it.next().copied() } + fn next_chunk<const N: usize>( + &mut self, + ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> + where + Self: Sized, + { + <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it) + } + fn size_hint(&self) -> (usize, Option<usize>) { self.it.size_hint() } @@ -166,3 +178,65 @@ where T: Copy, { } + +trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T> +where + T: Copy, +{ + fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>; +} + +impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I +where + I: Iterator<Item = &'a T>, + T: Copy, +{ + default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> { + array::iter_next_chunk(&mut self.map(|e| *e)) + } +} + +impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T> +where + T: Copy, +{ + fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> { + let mut raw_array = MaybeUninit::uninit_array(); + + let len = self.len(); + + if T::IS_ZST { + if len < N { + let _ = self.advance_by(len); + // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct + return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) }); + } + + let _ = self.advance_by(N); + // SAFETY: ditto + return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) }); + } + + if len < N { + // SAFETY: `len` indicates that this many elements are available and we just checked that + // it fits into the array. + unsafe { + ptr::copy_nonoverlapping( + self.as_ref().as_ptr(), + raw_array.as_mut_ptr() as *mut T, + len, + ); + let _ = self.advance_by(len); + return Err(array::IntoIter::new_unchecked(raw_array, 0..len)); + } + } + + // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize + // the array. + unsafe { + ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N); + let _ = self.advance_by(N); + Ok(MaybeUninit::array_assume_init(raw_array)) + } + } +} diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index 1e8d6bf3e..fbdeca4d4 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -64,19 +64,7 @@ where .into_try() } - #[inline] - fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> Acc, - { - #[inline] - fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { - move |acc, x| Ok(f(acc, x)) - } - - self.try_fold(init, ok(fold)).unwrap() - } + impl_fold_via_try_fold! { fold -> try_fold } } #[unstable(issue = "none", feature = "inplace_iteration")] diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index bf4fabad3..8cc2b7cec 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,5 +1,5 @@ use crate::iter::{InPlaceIterable, Iterator}; -use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try}; +use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; mod array_chunks; mod by_ref_sized; @@ -203,13 +203,7 @@ where .into_try() } - fn fold<B, F>(mut self, init: B, fold: F) -> B - where - Self: Sized, - F: FnMut(B, Self::Item) -> B, - { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 - } + impl_fold_via_try_fold! { fold -> try_fold } } #[unstable(issue = "none", feature = "inplace_iteration")] diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 80bfd2231..62470512c 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -74,19 +74,7 @@ where self.iter.try_fold(init, scan(state, f, fold)).into_try() } - #[inline] - fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> Acc, - { - #[inline] - fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { - move |acc, x| Ok(f(acc, x)) - } - - self.try_fold(init, ok(fold)).unwrap() - } + impl_fold_via_try_fold! { fold -> try_fold } } #[unstable(issue = "none", feature = "inplace_iteration")] diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index dbf0ae9ec..c6334880d 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -206,17 +206,7 @@ where if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() } } - fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - #[inline] - fn ok<Acc, T>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result<Acc, !> { - move |acc, x| Ok(f(acc, x)) - } - - self.try_rfold(init, ok(fold)).unwrap() - } + impl_fold_via_try_fold! { rfold -> try_rfold } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 2962e0104..58a0b9d7b 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -98,19 +98,7 @@ where } } - #[inline] - fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> Acc, - { - #[inline] - fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { - move |acc, x| Ok(f(acc, x)) - } - - self.try_fold(init, ok(fold)).unwrap() - } + impl_fold_via_try_fold! { fold -> try_fold } #[inline] #[rustc_inherit_overflow_checks] diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index ded216da9..ec66dc3ae 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -94,19 +94,7 @@ where } } - #[inline] - fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> Acc, - { - #[inline] - fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { - move |acc, x| Ok(f(acc, x)) - } - - self.try_fold(init, ok(fold)).unwrap() - } + impl_fold_via_try_fold! { fold -> try_fold } } #[stable(feature = "fused", since = "1.26.0")] |