What trait is used to perform a loop in a variable?

Hi, I was playing implementing iterators, then I noticed something....

How rust implements things like for i in var and for i in &var?

Seems like for var it access to var.into_iter() while for &var is for var.iter().

But at the same time for example, the method iter do not belongs to the Iterator trait...

So is like, how works the for loop in this case?

Thx!

the for loop is desugared using the IntoIterator trait, and &var actually desugared as (&var).into_iter(), for the standard containers, IntoIterator is implemented for the references (e.g. impl<'a, T> IntoIterator for &'a Vec<T>).

note, the desugar of for loop doesn't go through Deref.

5 Likes

thx! by curiosity, iter_mut belongs to any trait?

It does not. You can confirm this for yourself from the documentation: for example, find slice::iter_mut(), then scroll up to find the impl it belongs to ("Summary", collapsed items, view may be useful for this) and you will find impl<T> [T] — an inherent (non-trait) impl. You can tell it is not a trait impl because it does not have the “for” keyword in it — trait impls always look like impl MyTrait for MyType (with optional additional things on top of that) and inherent impls don't have the “MyTrait for” part.

The iter_mut method is not part of a trait directly, however by convention, a collection type would also offer the same functionality through IntoIter on a mutable reference.

For example: Vec<T> (via, [T]) has the .iter_mut method, but also, there's the implementation IntoIter for &mut Vec<T> (and also for &mut [T]) which offers the same functionality (it literally juts calls .iter_mut internally), powering in particular for x in &mut some_vec syntax to work as expected.

mmm, so look will handle each one with the next traits:

  • for x in &y: IntoIterator for &Y (fixed)
  • for x in y: IntoIterator for Y
  • for x in &mut y: IntoIterator for &mut Y

From here we could also implement, I suppose the complementary ones are not needed by conventions:

  • Iterator for &mut Y
  • Iterator for &Y
  • IntoIterator for &Y

Some of this ones can be almost equals with some of the first list....

IntoIterator for &Y. When it's for ... in ..., it's always IntoIterator.

Also, one almost never implements Iterator on the collection or a reference to it directly.

How is usually used the Iterator Trait? seems like IntoIterator does everything.

No. The desugared representation of

for element in iterable {}

is approximately

let mut iterator = iterable.into_iter();

while let Some(element) = iterator.next() {}
1 Like

IntoIterator is used to convert an object into a type that implements Iterator. The actual iteration is implemented via the Iterator trait, specifically via the Iterator::next method.

mmm, so IntoIterator just handle how to get any Iterator.

Iterator and .iter are not related.

Indeed. Hence its name. T::iter() is usually an inherent method on the type T which returns an Iterator over elements of T by convention.

Nitpick - over references to elements. For elements themselves, well, there's IntoIterator.

1 Like