Iterators

iter()

The .iter() method is a convention on slices ([T]) and standard collections (Vec<T>, VecDeque<T>, HashSet<T>, BTreeSet<T>) that borrows the collection immutably (&self) and returns an iterator yielding shared references (&T) to each element.

Signature and Item Type

On a slice [T] (and on Vec<T> via deref coercion), .iter() has the signature:

pub fn iter(&self) -> std::slice::Iter<'_, T>
// where Iter<'a, T>: Iterator<Item = &'a T>

Because .iter() only borrows the collection with &self, the collection remains intact and fully usable after iteration completes:

fn main() {
    let languages = vec![String::from("Rust"), String::from("C"), String::from("Zig")];

    // `.iter()` yields `&String`; `languages` is borrowed immutably, not consumed:
    for lang in languages.iter() {
        println!("Language: {lang} ({} bytes)", lang.len());
    }

    // `languages` is still owned and valid here:
    println!("Collection still has {} items: {languages:?}", languages.len());
}
Language: Rust (4 bytes)
Language: C (1 bytes)
Language: Zig (3 bytes)
Collection still has 3 items: ["Rust", "C", "Zig"]

equivalence of collection.iter() and for x in &collection

Standard collections implement IntoIterator for &Collection by delegating directly to .iter(). Therefore, these two loops are identical:

for item in &collection { /* item: &T */ }
for item in collection.iter() { /* item: &T */ }

Use &collection in for loops for brevity, and use .iter() when starting a method chain (collection.iter().filter(...).map(...)).

Double Reference in .iter().filter(...) (&&T)

Because .iter() produces items of type Item = &T, and .filter() passes a shared reference &Self::Item to its closure, a closure inside collection.iter().filter(...) receives a double reference (&&T). You can either dereference once with *, destructure with |&&x| (for Copy types), or compare against a reference:

fn main() {
    let scores = [72, 88, 95, 64, 91];

    // `scores.iter()` yields `&i32`; `.filter()` passes `&&i32` to the predicate:
    let high_scores: Vec<i32> = scores
        .iter()
        .filter(|&&score| score >= 90)
        .copied() // Converts `Iterator<Item = &i32>` -> `Iterator<Item = i32>`
        .collect();

    println!("High scores: {high_scores:?}");
}
High scores: [95, 91]

Converting Iterator<Item = &T> to Owned Values (.copied() and .cloned())

When an iterator yields &T from .iter() and you need owned T values downstream:

  • Call .copied() when T: Copy (copies each &T into T bitwise).
  • Call .cloned() when T: Clone (calls T::clone on each &T).