Example of How Rust Can be Confusing, Iteration and Refs

Posted on May 19, 2025 by Richard Goulter
Tags:

I recently tripped up over this when writing Rust:

Consider this example, which features a few different ways of iterating over arrays/vectors in Rust:

fn main() {
    let a: [u8; 3] = [3, 7, 5];
    let v: Vec<u8> = vec![3, 7, 5];

    for &x in &a {
        println!("{}", x);
    }
    for &x in a.iter() {
        println!("{}", x);
    }
    for x in a {
        println!("{}", x);
    }

    for &x in &v {
        println!("{}", x);
    }
    for &x in v.iter() {
        println!("{}", x);
    }
    for x in v {
        println!("{}", x);
    }
}

That code works.

With the array a, it iterates over &a, a.iter(), and a, as well as with the vector v over &v, v.iter(), and v.

Amending the example a bit, the following does not compile:

// Note: does NOT compile
fn main() {
    let a: [u8; 3] = [3, 7, 5];
    for &x in &a {
        println!("{}", x);
    }
    for &x in a.iter() {
        println!("{}", x);
    }
    for x in a {
        println!("{}", x);
    }
    for x in a { // added this `for`
        println!("{}", x);
    }

    let v: Vec<u8> = vec![3, 7, 5];
    for &x in &v {
        println!("{}", x);
    }
    for &x in &v.iter() { // changed to &v.iter()
        println!("{}", x);
    }
    for x in v {
        println!("{}", x);
    }
    for x in v { // added this `for`
        println!("{}", x);
    }
}

(Link to play.rust-lang.org)

What doesn’t work:

  1. The expression &v.iter() is incorrect.
  1. The for x in v { ... } consumes the value of v; so, v can’t be used after this.

Some notes for reference regarding the first point:

There’s no single thing about the above which I’d consider too confusing.

The documentation/references above are all for things which pretty much “just work”. And one mistaken assumption in the above code is about operator precedence.

I wanted to write about this because it’s a subtle case where incorrect expressions looked very similar to correct expressions.

It’s an example of something that I found surprising when writing Rust, and it’s not something that I’d have to think about if I were writing Python or TypeScript. (Or, the other way: it’s not something I’d have to think about when writing C).


Newer post Older post