Rust IntoIterator
IntoIterator is the trait that lets a value be walked item by item. The into_iter method comes from this trait.
for is into_iter in disguise
Every for loop calls into_iter() on the value, then pulls next() again and again until None:
let names = vec!["ada", "grace"];
for name in names {
println!("{name}");
}The same walk, written out
IntoIterator is the trait with one method: into_iter(self). It hands over an iterator — and takes the value by value, so the original is used up:
let numbers = [10, 20, 30];
let mut it = numbers.into_iter();
println!("{:?} {:?}", it.next(), it.next());Implement it for your own type
Set type Item to what comes out, and type IntoIter to the iterator type you hand over. The easiest honest implementation stores a Vec inside your type and returns that Vec's own iterator:
impl IntoIterator for Team {
type Item = String;
type IntoIter = std::vec::IntoIter<String>;
fn into_iter(self) -> Self::IntoIter {
self.members.into_iter()
}
}Then for just works
That one impl is all a for loop needs:
let team = Team {
members: vec![String::from("ada"), String::from("grace")],
};
for member in team {
println!("member = {member}");
}Example
use std::vec;
struct Team {
members: Vec<String>,
}
impl IntoIterator for Team {
type Item = String;
type IntoIter = vec::IntoIter<String>;
fn into_iter(self) -> Self::IntoIter {
self.members.into_iter()
}
}
fn main() {
let team = Team {
members: vec![String::from("ada"), String::from("grace")],
};
for member in team {
println!("member = {member}");
}
let numbers = [10, 20, 30];
let doubled: Vec<i32> = numbers.into_iter().map(|n| n * 2).collect();
println!("doubled = {:?}", doubled);
}Key points
- Vec, arrays, ranges, maps and sets all implement IntoIterator — that is why for works on all of them
- iter() and iter_mut() are not part of the trait.
- They are ordinary extra methods on collections.
- Use them when you want to borrow instead of take.
- Loop over &collection or .iter() when the collection must survive.
In this example, Team is a struct holding one Vec of names. Its IntoIterator impl says Item is String. It says IntoIter is the Vec's own iterator type. And into_iter simply hands over that iterator. That one impl is enough. The for loop walks the team. It prints member = ada and member = grace. The team is used up by the loop, exactly like a Vec would be. The last lines show the same trait at work in the standard library. An array's into_iter feeds map and collect. Together they build doubled = [20, 40, 60].
Note
Because into_iter takes self, looping over a collection with for uses it up, just like calling .into_iter() yourself.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
What does for x in thing do under the hood?