@@ -11,7 +11,7 @@ use crate::convert::Infallible;
1111use crate :: error:: Error ;
1212use crate :: hash:: { self , Hash } ;
1313use crate :: intrinsics:: transmute_unchecked;
14- use crate :: iter:: { UncheckedIterator , repeat_n} ;
14+ use crate :: iter:: { TrustedLen , UncheckedIterator , repeat_n} ;
1515use crate :: marker:: Destruct ;
1616use crate :: mem:: { self , ManuallyDrop , MaybeUninit } ;
1717use crate :: ops:: {
@@ -964,6 +964,12 @@ impl<T: [const] Destruct> const Drop for Guard<'_, T> {
964964 }
965965}
966966
967+ pub ( crate ) fn iter_next_chunk<T , const N : usize>(
968+ iter: & mut impl Iterator <Item = T >,
969+ ) -> Result <[ T ; N ] , IntoIter <T , N >> {
970+ iter. spec_next_chunk ( )
971+ }
972+ #[ inline]
967973/// Pulls `N` items from `iter` and returns them as an array. If the iterator
968974/// yields fewer than `N` items, `Err` is returned containing an iterator over
969975/// the already yielded items.
@@ -976,8 +982,7 @@ impl<T: [const] Destruct> const Drop for Guard<'_, T> {
976982/// dropped.
977983///
978984/// Used for [`Iterator::next_chunk`].
979- #[ inline]
980- pub( crate ) fn iter_next_chunk<T , const N : usize>(
985+ fn generic_iter_next_chunk<T , const N : usize >(
981986 iter: & mut impl Iterator <Item = T >,
982987) -> Result <[ T ; N ] , IntoIter <T , N >> {
983988 let mut array = [ const { MaybeUninit :: uninit ( ) } ; N ] ;
@@ -994,6 +999,32 @@ pub(crate) fn iter_next_chunk<T, const N: usize>(
994999 }
9951000}
9961001
1002+ pub ( crate ) trait SpecNextChunk < T , const N : usize > : Iterator < Item = T > {
1003+ fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , IntoIter < T , N > > ;
1004+ }
1005+ impl < I : Iterator < Item = T > , T , const N : usize > SpecNextChunk < T , N > for I {
1006+ default fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , IntoIter < T , N > > {
1007+ generic_iter_next_chunk ( self )
1008+ }
1009+ }
1010+
1011+ impl < I : Iterator < Item = T > + TrustedLen , T , const N : usize > SpecNextChunk < T , N > for I {
1012+ fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , IntoIter < T , N > > {
1013+ if self . size_hint ( ) . 0 < N {
1014+ let mut array = [ const { MaybeUninit :: uninit ( ) } ; N ] ;
1015+ // SAFETY: Has to error out; trusted len means that there may
1016+ // only be less than N elements
1017+ let initialized =
1018+ unsafe { iter_next_chunk_erased ( & mut array, self ) . unwrap_err_unchecked ( ) } ;
1019+ // SAFETY: Only the first `initialized` elements were populated
1020+ return Err ( unsafe { IntoIter :: new_unchecked ( array, 0 ..initialized) } ) ;
1021+ } else {
1022+ // SAFETY: must be at least N elements; safe to unwrap N elements.
1023+ return Ok ( from_fn ( |_| unsafe { self . next ( ) . unwrap_unchecked ( ) } ) ) ;
1024+ }
1025+ }
1026+ }
1027+
9971028/// Version of [`iter_next_chunk`] using a passed-in slice in order to avoid
9981029/// needing to monomorphize for every array length.
9991030///
0 commit comments