Unable to call reverse on a Zip Iterator zipping a std::iter::Repeat #104729
Description
Hello, first off sorry if this is not the right issue type, but I could not choose one that seemed to better fit. I tried to search in existing issues with "zip repeat rev" and nothing came up in GitHub. I don't know if it qualifies as a bug, but at least the behavior feels highly unintuitive.
I tried this code:
fn main() {
let vec_1 = vec![1; 10];
let zipped_iter = vec_1.iter().zip( std::iter::repeat(0));
println!("Forward");
for (one, zero) in zipped_iter {
println!("one: {one}, zero: {zero}");
}
let rev_vec_iter = vec_1.iter().rev();
let rev_repeat_iter = std::iter::repeat(0).rev();
// Manual reversed zip
let rev_zipped_iter = rev_vec_iter.zip(rev_repeat_iter);
println!("Backwards");
for (one, zero) in rev_zipped_iter {
println!("one: {one}, zero: {zero}");
}
println!("Now it gets tricky");
// This is illegal with the current next_back implementation of Zip
// Which requires ExactSizeIterator, which is not implemented by
// std::iter::repeat, so won't compile
let zipped_iter = vec_1.iter().zip( std::iter::repeat(0));
// Cannot call rev here for automatic reversed zip constuction
for (one, zero) in zipped_iter.rev() {
println!("one: {one}, zero: {zero}");
}
}
Rust playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=967385983c0fb72c27183385720fea8e
I expected to see this happen: the last iterator construction reversing the Zip iterator works the same as if I zipped two reverse iterator.
Instead, this happened: code does not compile because next_back implementation from Zip (ZipImpl::next_back) has ExactSizeIterator bounds for both iterator being zipped. std::iter::Repeat does not implement that trait. I'm not familiar with Zip internals or iterator internals but it seems it has to do with zip_impl_general_defaults which states:
#[inline]
default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
where
A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator,
{
// The function body below only uses `self.a/b.len()` and `self.a/b.next_back()`
// and doesn’t call `next_back` too often, so this implementation is safe in
// the `TrustedRandomAccessNoCoerce` specialization
Fails for all rustc versions in playground at the moment
Meta
rustc --version --verbose
:
rustc --version --verbose
rustc 1.65.0 (897e37553 2022-11-02)
binary: rustc
commit-hash: 897e37553bba8b42751c67658967889d11ecd120
commit-date: 2022-11-02
host: x86_64-unknown-linux-gnu
release: 1.65.0
LLVM version: 15.0.0
Backtrace
Compiling playground v0.0.1 (/playground)
error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the trait bound `std::iter::Repeat<{integer}>: ExactSizeIterator` is not satisfied
--> src/main.rs:33:24
|
33 | for (one, zero) in zipped_iter.rev() {
| ^^^^^^^^^^^ --- required by a bound introduced by this call
| |
| the trait `ExactSizeIterator` is not implemented for `std::iter::Repeat<{integer}>`
|
= help: the following other types implement trait `ExactSizeIterator`:
&mut I
Args
ArgsOs
ArrayChunksMut<'_, T, N>
ArrayWindows<'_, T, N>
Box<I, A>
Chunks<'_, T>
ChunksExact<'_, T>
and 108 others
= note: required for `Zip<std::slice::Iter<'_, {integer}>, std::iter::Repeat<{integer}>>` to implement `DoubleEndedIterator`
note: required by a bound in `rev`
error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the trait bound `std::iter::Repeat<{integer}>: ExactSizeIterator` is not satisfied
--> src/main.rs:33:24
|
33 | for (one, zero) in zipped_iter.rev() {
| ^^^^^^^^^^^^^^^^^ the trait `ExactSizeIterator` is not implemented for `std::iter::Repeat<{integer}>`
|
= help: the following other types implement trait `ExactSizeIterator`:
&mut I
Args
ArgsOs
ArrayChunksMut<'_, T, N>
ArrayWindows<'_, T, N>
Box<I, A>
Chunks<'_, T>
ChunksExact<'_, T>
and 108 others
= note: required for `Zip<std::slice::Iter<'_, {integer}>, std::iter::Repeat<{integer}>>` to implement `DoubleEndedIterator`
= note: required for `Rev<Zip<std::slice::Iter<'_, {integer}>, std::iter::Repeat<{integer}>>>` to implement `Iterator`
= note: required for `Rev<Zip<std::slice::Iter<'_, {integer}>, std::iter::Repeat<{integer}>>>` to implement `IntoIterator`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to 2 previous errors