Why was `Iterator` moved to associated types?


#1

I searched but couldn’t find the discussion, what what the rationale behind this move?

It is a major drawback in functionality because it is not possible to overload the iterator trait any more, that means only one Iterator implementation per type (unless I introduce some marker type). Or is it planned to allow overloading with associated types at some point?


#2

It’s not intended to allow overloading in that way. (Link to original associated items RFC). The intention is that associated types are “output” types… they are entirely determined by input types (Self type and type parameters on the trait). This should guide and improve type inference.

Associated types have many upsides and it removes the need for redundant type parameters everywhere. The Map iterator adaptor is nowadays just Map<I, F> (Iterator and function) and no redundant type parameters (it used to be something like Map<A, B, I, F>).

Here’s an example of simple code that is nicer without redundant type parameters:

/// An iterator adaptor that allows putting back a single
/// item to the front of the iterator.
pub struct PutBack<I> where
    I: Iterator,
{
    top: Option<I::Item>,
    iter: I,
}

impl<I> PutBack<I> where
    I: Iterator,
{
    /// Put back a single value to the front of the iterator.
    /// If a value is already in the put back slot, it is overwritten.
    pub fn put_back(&mut self, x: I::Item)
    {
        self.top = Some(x)
    }
}

impl<I> Iterator for PutBack<I> where
    I: Iterator,
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        match self.top {
            None => self.iter.next(),
            ref mut some => some.take(),
        }
    }
}

#3

I see. Thanks for the link to the original RFC. It is especially convincing for the Add-trait. I’m still not convinced that it is good for Iterator but probably it is you mostly need a specialized iterator type anyway.