Collect() method implementation of IntoIter structure

I was looking at how the collect method is implemented for the IntoIter structure.

    fn collect<B: FromIterator<Self::Item>>(self) -> B
    where
        Self: Sized,
    {
        // This is too aggressive to turn on for everything all the time, but PR#137908
        // accidentally noticed that some rustc iterators had malformed `size_hint`s,
        // so this will help catch such things in debug-assertions-std runners,
        // even if users won't actually ever see it.
        if cfg!(debug_assertions) {
            let hint = self.size_hint();
            assert!(hint.1.is_none_or(|high| high >= hint.0), "Malformed size_hint {hint:?}");
        }

        FromIterator::from_iter(self)
    }

I have a couple of questions -

  1. What does Self::Item represent here? Does it mean IntoIter::Item or <IntoIter as Iterator>::Item ?.
  2. How is this code able to call from_iter() like this? Why does it not need call syntax as <B as FromIterator>::from_iter(self)?

I wrote some sample code to mimic collect()'s call semantics and compiler complains that I have to use fully qualified path like <struct as trait>::method(). But in here, compiler is fine. Why?

Thanks!

The latter. Note also that this is the default method body for the Iterator trait.

The return type guides inference -- it's expecting to return a B from the method signature, and FromIterator::from_iterator returns the implementing type of FromIterator.

Hard to be completely sure without seeing the code, but presumably it's not expecting any particular type in your code. You can probably use one of these instead of a fully qualified path.

    let __: B = FromIterator::from_iter(iter);
    let __ = B::from_iter(iter);
1 Like

Thanks @quinedot. The return type was it. My trait method implementation was not returning any type. Once I added that, like you said, type inference worked without <struct as trait> syntax.

Where can I read more about nuances of type inference in Rust?
Thanks!

PS: This was my experiment code to mimic collect method call semantics and experiment with trait implementation with specific item types.

trait Bird {
    type Item;
    fn get() -> Self;
}

trait Convert {
    type Item;
    fn convert<T: Bird<Item = Self::Item>>(&self) -> T;
}

#[derive(Debug)]
struct Animal;

impl Convert for Animal {
    type Item = String;
    fn convert<T: Bird<Item = Self::Item>>(&self) -> T {
        Bird::get()
    }
}

#[derive(Debug)]
struct Parrot;

impl Bird for Parrot {
    type Item = String;
    
    fn get() -> Parrot {
        Parrot
    }
}

#[derive(Debug)]
struct Duck;

impl Bird for Duck {
    type Item = u32;
    
    fn get() -> Duck {
        Duck
    }
}

fn main() {
    let a = Animal;
    
    let p = &a.convert::<Parrot>();
    println!("{:?}", p);
    
    //let d = &a.convert::<Duck>(); //won't compile due to Item type mismatch
    //println!("{:?}", d);
}