Iterators

into_iter()

The .into_iter() method, defined by the IntoIterator trait, consumes its receiver by value (self) and converts it into an Iterator.

Context-Dependent Behavior of .into_iter()

Because IntoIterator is implemented separately for owned collections (T), shared references (&T), and mutable references (&mut T), what .into_iter() yields depends on the receiver type it is called on:

Receiver Expression Receiver Type Item Yielded by .into_iter() Equivalent Method
vec.into_iter() Vec<T> (owned) T (moves each element out and drops the Vec buffer) Owned consumption
(&vec).into_iter() &Vec<T> &T vec.iter()
(&mut vec).into_iter() &mut Vec<T> &mut T vec.iter_mut()

Moving Owned Elements Out of a Collection

Calling .into_iter() on an owned Vec<T>, [T; N], HashSet<T>, or HashMap<K, V> transfers ownership of every element out of the collection without cloning:

fn main() {
    let messages = vec![
        String::from("init"),
        String::from("ready"),
        String::from("shutdown"),
    ];

    // Moves each `String` out of `messages` and appends "!" in place:
    let shouting: Vec<String> = messages
        .into_iter()
        .map(|mut msg| {
            msg.push('!');
            msg.to_uppercase()
        })
        .collect();

    println!("{shouting:?}");
}
["INIT!", "READY!", "SHUTDOWN!"]

Once messages.into_iter() is called, messages has been moved and cannot be accessed again (E0382):

// ❌ does not compile
fn main() {
    let names = vec![String::from("Alice"), String::from("Bob")];
    let _iter = names.into_iter();
    println!("{names:?}");
}
error[E0382]: borrow of moved value: `names`
 --> src/main.rs:5:15
  |
3 |     let names = vec![String::from("Alice"), String::from("Bob")];
  |         ----- move occurs because `names` has type `Vec<String>`, which does not implement the `Copy` trait
4 |     let _iter = names.into_iter();
  |                       ----------- `names` moved due to this method call
5 |     println!("{names:?}");
  |               ^^^^^^^ value borrowed here after move
  |
help: consider calling `.iter()` instead of `.into_iter()` to borrow `names`

Fixed-Size Array .into_iter() (Rust 2021 and 2024 Editions)

Fixed-size arrays [T; N] implement IntoIterator<Item = T> by value, so calling [a, b, c].into_iter() yields owned T elements directly:

fn main() {
    let arr = [String::from("one"), String::from("two")];

    for word in arr.into_iter() {
        // `word` is an owned `String`, not `&String`
        println!("Owned word: {word}");
    }
}
Owned word: one
Owned word: two