Why Vec::into_iter() is consuming self?

Hi,

I cannot understand why Vec::into_iter() is consuming self despite IntoIterator trait is implemented for &Vec (see here).

Consider this little example, as you can see since I've implemented IntoIterator for & Foo, into_iter() is not consuming my instance.

I cannot see where is the catch :woozy_face: :thinking:

Thank you

It consumes self because you are calling the impl of IntoIterator for Vec<T>, and not the one for &Vec<T>. If you want the other one, you can use the .iter() method.

To actually use into_iter for this, you can call it like this:

IntoIterator::into_iter(&vec)
3 Likes

To give the full picture, there are three implementations

impl IntoIterator for <Vec<T>> {
    type Item = T;
    type IntoIter = vec::IntoIter<T>;
    fn into_iter(self: Vec<T>) -> vec::IntoIter<T>;
}
impl IntoIterator for <&Vec<T>> {
    type Item = &T;
    type IntoIter = vec::Iter<'_, T>;
    fn into_iter(self: &Vec<T>) -> vec::Iter<'_, T>;
}
impl IntoIterator for <&mut Vec<T>> {
    type Item = &mut T;
    type IntoIter = vec::IterMut<'_, T>;
    fn into_iter(self: &mut Vec<T>) -> vec::IterMut<'_, T>;
}

(ignoring lifetimes for these implementations).

Thus, calling (&vec).into_iter() is the same as vec.iter() and (&mut vec).into_iter() is the same as vec.iter_mut(). (On a variable vec: Vec<T>.)


As @Cerber-Ursi mentioned below, there’s a rule that an implementation on the type itself is preferred. So writing vec.into_iter() on a vec: Vec<T> will first try to use the IntoIterator for Vec<T> implementation before it would’ve tried adding a reference and using IntoIterator for &Vec<T>.

More details on the order of self-types that are tried/considered for a method called can be found here. For Vec<T>, the following receiver types are tried in order: Vec<T>, &Vec<T>, &mut Vec<T>, [T], &[T], &mut [T]. Since the first one, Vec<T> by-value already supports an into_iter method, that’s what‘s used. For your example with Foo, the order is Foo, &Foo and &mut Foo. There is no fn into_iter(self: Foo) method, but a fn into_iter(self: &Foo) method exists so that is chosen.

4 Likes

But once you add impl IntoIterator for Foo, it takes precedence over implementation for &Foo. The same thing is with Vec.

2 Likes

Sorry guys, I just didn't see that few lines above there was the documentation for impl<T, A> IntoIterator for Vec<T, A> :man_facepalming:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.