@@ -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:: {
@@ -976,9 +976,15 @@ impl<T: [const] Destruct> const Drop for Guard<'_, T> {
976976 /// dropped.
977977///
978978 /// Used for [ `Iterator :: next_chunk`] .
979- #[ inline]
980979pub ( crate ) fn iter_next_chunk<T , const N : usize>(
981980 iter: & mut impl Iterator <Item = T >,
981+ ) -> Result <[ T ; N ] , IntoIter <T , N >> {
982+ iter. spec_next_chunk ( )
983+ }
984+
985+ #[ inline]
986+ fn generic_iter_next_chunk<T , const N : usize>(
987+ iter: & mut impl Iterator <Item = T >,
982988) -> Result <[ T ; N ] , IntoIter <T , N >> {
983989 let mut array = [ const { MaybeUninit :: uninit ( ) } ; N ] ;
984990 let r = iter_next_chunk_erased ( & mut array, iter) ;
@@ -994,6 +1000,32 @@ pub(crate) fn iter_next_chunk<T, const N: usize>(
9941000 }
9951001}
9961002
1003+ pub ( crate ) trait SpecNextChunk < T , const N : usize > : Iterator < Item = T > {
1004+ fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , IntoIter < T , N > > ;
1005+ }
1006+ impl < I : Iterator < Item = T > , T , const N : usize > SpecNextChunk < T , N > for I {
1007+ default fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , IntoIter < T , N > > {
1008+ generic_iter_next_chunk ( self )
1009+ }
1010+ }
1011+
1012+ impl < I : Iterator < Item = T > + TrustedLen , T , const N : usize > SpecNextChunk < T , N > for I {
1013+ fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , IntoIter < T , N > > {
1014+ if self . size_hint ( ) . 0 < N {
1015+ let mut array = [ const { MaybeUninit :: uninit ( ) } ; N ] ;
1016+ let initialized =
1017+ // SAFETY: Has to error out; trusted len means that
1018+ // SAFETY: there may only be less than N elements
1019+ unsafe { iter_next_chunk_erased ( & mut array, self ) . unwrap_err_unchecked ( ) } ;
1020+ // SAFETY: Only the first `initialized` elements were populated
1021+ Err ( unsafe { IntoIter :: new_unchecked ( array, 0 ..initialized) } )
1022+ } else {
1023+ // SAFETY: must be at least N elements; safe to unwrap N elements.
1024+ Ok ( from_fn ( |_| unsafe { self . next ( ) . unwrap_unchecked ( ) } ) )
1025+ }
1026+ }
1027+ }
1028+
9971029/// Version of [`iter_next_chunk`] using a passed-in slice in order to avoid
9981030/// needing to monomorphize for every array length.
9991031///
0 commit comments