Why doesn't `Vec` implement `ExactSizeIterator`

A std::Vec has a .len() method, but ExactSizeIterator is not implemented for it. This is inconvenient. Is this a design decision or just an omission (that could be fixed in a future Rust release)?

let vector = vec![3i32, 4, 5];
test(vector);

fn test(vector: impl ExactSizeIterator) {
    println!("size is {}", vector.len());
}

results in a compile error:

the trait `ExactSizeIterator` is not implemented for `Vec<i32>`

Vec is not an iterator. It can be converted into an iterator, but that's not that you're doing here.

4 Likes

Iterators are decoupled from storage, i.e. collections and their iterators are different types. This is done so because otherwise:

  1. the collection would have to maintain iteration state itself, which is undesirable for several reasons:
  • what does it mean for a vector to have a "current" element?
  • how do you define "the" current element when there are more than 1 iterators to the same vector?
  • how do you iterate over non-owning types (e.g. a slice), which can't store additional state?
  1. it would not be possible to obtain different kinds of iterators (i.e., owning, borrowing, mutably borrowing) from the same collection.

What you are probably looking for instead is:

fn test<T>(iter: T)
where
    T: IntoIterator,
    T::IntoIter: ExactSizeIterator,
{
    println!("size is {}", iter.into_iter().len());
}
10 Likes

Changing test(vector); to test(vector.into_iter()); would also work.

2 Likes

Thanks for your nice, explanatory, answer, in retrospect this makes sense. At first sight it just seemed so logical for Vec to implement ExactSizeIterator...

Seemingly I need to explore the 'advanced' topics on generics (and iterators) a bit further.. :slight_smile: