Repository navigation
Open
Labels
A-autovectorizationArea: Autovectorization, which can impact perf or code sizeArea: Autovectorization, which can impact perf or code sizeC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Description
Feature gate: #![feature(iter_next_chunk)]
This is a tracking issue for the .next_chunk() and .next_chunk_back() method on iterators which allows you to advance the iterator N elements and return an array [T; N]
Public API
use core::array;
trait Iterator {
type Item;
fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
where
Self: Sized;
}
trait DoubleEndedIterator {
fn next_chunk_back<const N: usize>(&mut self) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
where
Self: Sized;
}Steps / History
- Implementation:
- Add
Iterator::next_chunk#93700 - Optimized vec::IntoIter::next_chunk impl #98553
- Optimize
slice_iter.copied().next_chunk()#103166 - optimize next_chunk impls for Filter and FilterMap #111781
- fix Drop items getting leaked in Filter::next_chunk #126879
- Implement
DoubleEndedIterator::next_chunk_back#156737
- Add
- Final comment period (FCP)
- Stabilization PR
Unresolved Questions
- Naming: other options include
next_array()ornext_array_chunk(). - How should we handle
N = 0?
Reacted by dullbananas, Mikaël Gourlaouen, figsoda, Ivan Sadílek, Denis Kotlyarov, Sophie Herold, Alex1005a, Joe Grund, Robert, Matt and 23 more
Reacted by Caret, mark, Ryan Moodie, Pavel Skipenes, Heitor de Bittencourt, Andreas Botzner, Markus Kasten, Aaron Suggs, Proc, MidAutumnMoon and 26 more
Metadata
Metadata
Assignees
Labels
A-autovectorizationArea: Autovectorization, which can impact perf or code sizeArea: Autovectorization, which can impact perf or code sizeC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Activity
ChayimFriedman2 commentedon Jun 21, 2022
Should this method support
N=0?itertoolsdoes not, and it sounds plausible; however, if we want to do the same, we will have the same concern as<[T]>::array_chunks()that cannot be stabilized untilgeneric_const_exprsor some subset will be stabilized.the8472 commentedon Jun 25, 2022
I'm wondering about the intended uses of this API.
If it is for performance (autovectorization) then it seems fairly brittle. I just tried doing this benchmark:
and it took
17,272 ns/iterwhen compiled withtarget-cpu=znver2. With a handrolled implementation I got211 ns/iter. I encountered some 10x slowdowns in a few other combinations. Sometimescodegen-units=1produced even worse assembly because vectorizer did silly things such as loading one byte at a time into a simd register withvpinsrb.And that's with direct, linear memory access on a
Vec::IntoIterwhich should be relatively straight-forward to turn into masked simd loads. Many iterators yield references. A[&T; N]would need a gather-load which is expensive and only available on newer CPUs, this is unlikeslice::array_chunkswhich yields&[T; N]. We could try specializingslice.iter().next_chunk()but then you might as well usearray_chunks. And of course it'll get more complex with additional adapters.Another limitation is that it can't be used in a for-in loop or chained further with other iterator adapters, an issue #92393 didn't have.
Lokathor commentedon Sep 7, 2022
This is probably an example of a case where you should first use
copied(), and then chunk it, and then you turn that array into a simd type for the work, before possibly turning it back at the end of your loop.And the change into and out of simd form will have a cost, so you'll want to ensure you're doing enough work inside each loop pass or it might exceed the cost of the scalar only code.
the8472 commentedon Sep 7, 2022
yeah that was just an example to illustrate that the default implementation is suboptimal and we'll need optimized implementations on most linear-memory sources and length-preserving adapters.
Lokathor commentedon Sep 7, 2022
Mm, yeah.
Myself I would imagine using this most on iterators that aren't linear memory sources, and "the point" would be to have a clean and unified way to turn some crazy data source into simple SIMD chunks.
rossmacarthur commentedon Nov 1, 2022
Might be good to align the naming of this function with
Iterator::array_chunks, i.e. eitherIterator::chunksIterator::next_chunkOr
Iterator::array_chunksIterator::next_array_chunkmark-i-m commentedon Jan 24, 2023
So I'm finding myself caring less and less about the actual naming. I've wanted this feature at least 3 times in the last year and had to write my own version to get around. Can we just pick something and get the feature stabilized?
ZhennanWu commentedon Apr 23, 2023
I believe the current implementation also suffers from this compiler optimization issue: #110734
Godbolt: https://godbolt.org/z/Te5Wo9eh7
the8472 commentedon Apr 23, 2023
I'm not sure what that issue has to do with
next_chunkspecifically. It seems to be mostly about the codegen forit.collect::<Vec<_>>(), which I think is easily disturbed by anything mutating the iterator.pitaj commentedon May 25, 2023
Let's get this stabilized. Here are my answers to the Unresolved Questions:
next_chunkseems like the best option to me.Probably, but that should be under a separate feature and not block this.
It should be allowed and return a zero-length array without advancing the iterator. No good reason to forbid it.
the8472 commentedon May 25, 2023
For
next_chunkit might not be a problem but for the chunks iterators on slices and for iterator.array_chunks() it is. So we might as well do something about it herepitaj commentedon May 25, 2023
I disagree. For those, it's necessary by definition. There's no reason to apply the same logic here besides, in my opinion, a misguided desire for consistency. The behavior of
next_chunkis totally reasonable for array length 0, unlike the others you mentioned."Doing something about it" will pretty much require const expressions just like all the other ones, needlessly delaying the stabilization.
the8472 commentedon May 25, 2023
Well, it would prevent implementations of
next_chunkusing those things internally22 remaining items
hanna-kruppe commentedon Dec 24, 2025
The other alternative here is to piggy-back on some future language feature for in-place initialization, which also has to address fallibility somehow. The downside of transparently making the current API lower to "out-ptr for Some/Ok payload" ABI is that it also fails transparently: whenever move elimination doesn't fire for any reason, or a pointer to an entire
Result<[T; N], _>is required, codegen will be just as inefficient as today, without any clue at the source level.In contrast, most in-place-init proposals have some explicit opt-in at the call site that guarantees no extra moves or temporaries. That's necessary for soundness in some use cases, but it's also useful for types (here: array lengths) large enough to overflow the stack. The downside is that there's some extra annotation burden, which may be a bad trade-off for an API that's partly about convenience. But depending on which (if any) approach is adopted, maybe the common case is succinct enough to be attractive for this API, too.
Rollup merge of rust-lang#149131 - bend-n:optimize_slice_iter_next_ch…
Rollup merge of rust-lang#150230 - bend-n:trusted_len_spec_for_iter_n…
Rollup merge of rust-lang#150230 - bend-n:trusted_len_spec_for_iter_n…
Unrolled build for #150230
asder8215 commentedon May 19, 2026
Are we able to add
DoubleEndedIterator::next_chunk_backunderneath this tracking issue? The person who made the ACP for this method and the original PR had it marked under#![feature(iter_next_chunk)]feature gated. I picked up the PR here to get it over the finish line due to inactivity.Rollup merge of rust-lang#156737 - asder8215:double_ended_iterator_ne…
Auto merge of #156737 - asder8215:double_ended_iterator_next_chunk_ba…
Rollup merge of rust-lang#156737 - asder8215:double_ended_iterator_ne…
Unrolled build for #156737
aapoalas commentedon Jul 3, 2026
Added
.next_chunk_back()to the tracking issue.asder8215 commentedon Jul 3, 2026
@aapoalas to note,
.next_chunk_back()should be underneath theDoubleEndedIteratortrait notIteratortrait.giang299 commentedon Jul 11, 2026
IT MUST BE next_chunk()
next_chunk is amz naming. we already have a Vec::chunks(),..etc before, it's universal.