Iterators
Implementing IntoIterator
Implementing std::iter::IntoIterator on a custom collection enables it to be used directly in for loops and passed to generic functions bounded by IntoIterator.
Implementing IntoIterator for Owned (T) and Borrowed (&T, &mut T) Receivers
A complete collection typically provides up to three IntoIterator implementations:
| Implementation Target | Item Type |
IntoIter Type |
Purpose |
|---|---|---|---|
impl<T> IntoIterator for MyCollection<T> |
T |
Owned iterator (or wrapped std::vec::IntoIter<T>) |
for x in collection |
impl<'a, T> IntoIterator for &'a MyCollection<T> |
&'a T |
Borrowed iterator (or std::slice::Iter<'a, T>) |
for x in &collection |
impl<'a, T> IntoIterator for &'a mut MyCollection<T> |
&'a mut T |
Mutable iterator (or std::slice::IterMut<'a, T>) |
for x in &mut collection |
Delegating IntoIterator to an Inner Collection
When your custom collection wraps a standard container such as Vec<T>, you can reuse std::vec::IntoIter<T>, std::slice::Iter<'a, T>, and std::slice::IterMut<'a, T> as your IntoIter associated types without writing custom iterator state machines from scratch:
pub struct Playlist {
tracks: Vec<String>,
}
impl Playlist {
pub fn new(tracks: Vec<String>) -> Self {
Self { tracks }
}
pub fn iter(&self) -> std::slice::Iter<'_, String> {
self.tracks.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, String> {
self.tracks.iter_mut()
}
}
// 1. Owned iteration: `for track in playlist`
impl IntoIterator for Playlist {
type Item = String;
type IntoIter = std::vec::IntoIter<String>;
fn into_iter(self) -> Self::IntoIter {
self.tracks.into_iter()
}
}
// 2. Shared reference iteration: `for track in &playlist`
impl<'a> IntoIterator for &'a Playlist {
type Item = &'a String;
type IntoIter = std::slice::Iter<'a, String>;
fn into_iter(self) -> Self::IntoIter {
self.tracks.iter()
}
}
// 3. Mutable reference iteration: `for track in &mut playlist`
impl<'a> IntoIterator for &'a mut Playlist {
type Item = &'a mut String;
type IntoIter = std::slice::IterMut<'a, String>;
fn into_iter(self) -> Self::IntoIter {
self.tracks.iter_mut()
}
}
fn main() {
let mut list = Playlist::new(vec![
String::from("Intro"),
String::from("Main Theme"),
]);
// Uses `impl IntoIterator for &mut Playlist`:
for track in &mut list {
track.push_str(" (Remastered)");
}
// Uses `impl IntoIterator for &Playlist`:
for track in &list {
println!("Borrowed: {track}");
}
// Uses `impl IntoIterator for Playlist` (consumes `list`):
let owned: Vec<String> = list.into_iter().collect();
println!("Collected owned: {owned:?}");
}
Borrowed: Intro (Remastered)
Borrowed: Main Theme (Remastered)
Collected owned: ["Intro (Remastered)", "Main Theme (Remastered)"]