Does a for loop operate on references or by value?

Viewed 160

This aspect of Rust seems rather bizarre at first, and I'd like to know how for typing works in this case.

fn sum1(v: &mut Vec<i32>) -> i32 {
    // I know I don't mutate v, but that's not the point
    let mut s = 0;
    for e in v {
        s += *e;
        // s += e; <- Err!
    }
    s
}

fn sum2(v: &Vec<i32>) -> i32 {
    let mut s = 0;
    for e in v {
        s += e; // Okay?
    }
    s
}

fn main() {
    let mut v = vec![1, 2, 3];
    println!("{}", sum1(&mut v));
    println!("{}", sum2(&v));
}

At first I was confused as to why it wanted me to dereference in sum1. But okay, it's saying AddAssign<&mut i32> is not implemented, so I see that e is &mut i32. That's really awesome for changing e on the fly.

But now, with that information, why does sum2 compile? It seems like AddAssign<&i32> is indeed implemented (Which I tested separately), so it's possible that it's using that AddAssign method on a &i32, but then again it's also possible that e is simply i32. My question boils down to:

Is e an i32, or an &i32?

I don't know enough about references to easily check the difference myself (By using something other than i32 and checking for crashes). &i32 is the most logical but I would like to know for sure.

Coming from C, mixing between pointers and values is extremely confusing, and it has already taken me quite a bit to get used to with functions automatically dereferencing/referencing their arguments (which I don't think I've really done yet).

EDIT:

The type could be verified (And answer my question) with How do I print the type of a variable in Rust?, which is useful to mess around with but doesn't directly answer how for loops work. What is the exact definition of the for loop in Rust? helps a lot, and What is the difference between iter and into_iter? talks about a related IntoIterator trait that can cause for loop confusion.

0 Answers
Related