Essential Standard Traits

IntoIterator

The IntoIterator trait in std::iter defines how a type (or a reference to a type) converts into an Iterator, powering for loops across the language.

Trait Definition

pub trait IntoIterator {
    type Item;
    type IntoIter: Iterator<Item = Self::Item>;

    fn into_iter(self) -> Self::IntoIter;
}

Every type that implements Iterator automatically implements IntoIterator via a standard library blanket implementation (impl<I: Iterator> IntoIterator for I), returning itself from into_iter(self).

Desugaring of for Loops

A for loop in Rust is syntactic sugar for IntoIterator::into_iter:

// High-level syntax:
for item in collection {
    // body
}

// Compiler desugaring:
{
    let mut iter = IntoIterator::into_iter(collection);
    while let Some(item) = iter.next() {
        // body
    }
}

Three IntoIterator Implementations on Standard Collections

Standard collections such as Vec<T> implement IntoIterator three times—once for the owned type Vec<T>, once for &Vec<T>, and once for &mut Vec<T>—so the for loop syntax controls ownership directly:

for Loop Target IntoIterator Implemented On Item Type Equivalent Method on Vec<T>
for x in &vec &'a Vec<T> &'a T vec.iter()
for x in &mut vec &'a mut Vec<T> &'a mut T vec.iter_mut()
for x in vec Vec<T> T (consumes vec) vec.into_iter()
fn main() {
    let mut nums = vec![10, 20, 30];

    // 1. Shared reference (&Vec<i32> -> Item = &i32)
    for n in &nums {
        print!("{n} ");
    }
    println!();

    // 2. Mutable reference (&mut Vec<i32> -> Item = &mut i32)
    for n in &mut nums {
        *n += 5;
    }

    // 3. By value (Vec<i32> -> Item = i32, consumes nums)
    for n in nums {
        print!("{n} ");
    }
    println!();
}
10 20 30 
15 25 35 

Accepting Any Iterable in Functions

Bounding a function parameter with impl IntoIterator<Item = T> lets callers pass a Vec<T>, an array [T; N], a HashSet<T>, or a chained iterator adapter directly without calling .into_iter() or .collect() at the call site:

fn average(values: impl IntoIterator<Item = f64>) -> f64 {
    let mut sum = 0.0;
    let mut count = 0usize;
    for v in values {
        sum += v;
        count += 1;
    }
    if count == 0 { 0.0 } else { sum / count as f64 }
}

fn main() {
    println!("Array avg:  {:.1}", average([2.0, 4.0, 6.0]));
    println!("Range map:  {:.1}", average((1..=5).map(f64::from)));
}
Array avg:  4.0
Range map:  3.0