Under which conditions does Rust cache function or method results?

I am still unsure when we should better save function or method results in local variables to avoid multiple evaluations. Consider the trivial example

fn remove_zeros(v: &mut Vec<i32>) {
    let l = v.len();
    let mut d = 0;
    let mut s = 0;
    while s < l {
        v[d] = v[s];
        if v[d] != 0 {
            d += 1;
        }
        s += 1;
    }
    v.truncate(d);
}

fn main() {
    let mut v: Vec<i32> = vec![0, 1, 0, 2, 0, 0, 3, 0];
    remove_zeros(&mut v);
    println!("{:?}", v);
}

Do we need the variable l, or would it be guaranteed that

while s < v.len() {

compile to identical code? I think some programming language have the concept of pure functions, which are guaranteed to return always the same result for the same arguments and do not modify global state. But for the concrete example above, the vector is mut, so the concept of pure functions might not help.

It is not guaranteed, but LLVM will most likely inline the v.len() call to just read the length field of v. In this particular case then it should be able to see that nothing is modifying that field and thus cache its value in a register. If you are unsure you can check on godbolt, where you can see that in this case there's virtually no difference between using l or not.

4 Likes