Skip to content

Commit 9a48fb6

Browse files
committed
optimize slice::Iter::next_chunk
1 parent c797096 commit 9a48fb6

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

library/core/src/slice/iter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl<'a, T> Iter<'a, T> {
139139
}
140140
}
141141

142-
iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, {
142+
iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, each_ref, {
143143
fn is_sorted_by<F>(self, mut compare: F) -> bool
144144
where
145145
Self: Sized,
@@ -368,7 +368,7 @@ impl<T> AsRef<[T]> for IterMut<'_, T> {
368368
// }
369369
// }
370370

371-
iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, as_mut, {}}
371+
iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, as_mut, each_mut, {}}
372372

373373
/// An internal abstraction over the splitting iterators, so that
374374
/// splitn, splitn_mut etc can be implemented once.

library/core/src/slice/iter/macros.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ macro_rules! iterator {
6868
$raw_mut:tt,
6969
{$( $mut_:tt )?},
7070
$into_ref:ident,
71+
$array_ref:ident,
7172
{$($extra:tt)*}
7273
) => {
7374
impl<'a, T> $name<'a, T> {
@@ -190,6 +191,29 @@ macro_rules! iterator {
190191
}
191192
}
192193

194+
fn next_chunk<const N:usize>(&mut self) -> Result<[$elem; N], crate::array::IntoIter<$elem, N>> {
195+
if T::IS_ZST {
196+
return crate::array::iter_next_chunk(self);
197+
}
198+
let len = len!(self);
199+
if len >= N {
200+
// SAFETY: we are just getting an array of [T; N] and moving the pointer over a little
201+
let r = unsafe { self.post_inc_start(N).cast_array().$into_ref() }
202+
.$array_ref(); // must convert &[T; N] to [&T; N]
203+
Ok(r)
204+
} else {
205+
// cant use $array_ref because theres no builtin for &mut [MU<T>; N] -> [&mut MU<T>; N]
206+
// cant use copy_nonoverlapping as the $elem is of type &{mut} T instead of T
207+
let mut a = [const { crate::mem::MaybeUninit::<$elem>::uninit() }; N];
208+
for into in (&mut a).into_iter().take(len) {
209+
// SAFETY: take(n) limits to remainder (slice produces worse codegen)
210+
into.write(unsafe { self.post_inc_start(1).$into_ref() });
211+
}
212+
// SAFETY: we just initialized elements 0..len
213+
unsafe { Err(crate::array::IntoIter::new_unchecked(a, 0..len)) }
214+
}
215+
}
216+
193217
#[inline]
194218
fn size_hint(&self) -> (usize, Option<usize>) {
195219
let exact = len!(self);

0 commit comments

Comments
 (0)