rusttuplessemanticsoperator-precedencelanguage-specifications

What is the evaluation order of tuples in Rust?


Tuple elements may have side-effects, and some of them may depend on others. Consider this program:

fn main() {
    let mut v = vec![1, 2];
    match (v.pop(), v.pop()) {
        (Some(z), Some(y)) => println!("y = {}, z = {}", y, z),
        _ => unreachable!(),
    }
}

Does it output y = 1, z = 2 or y = 2, z = 1? A few rounds on the Rust Playground suggests the former on stable 1.32.0, but maybe it would change if I ran it more times, recompiled the compiler, changed compiler versions, etc.

Is there a documented commitment or at least intention to maintain a particular order of evaluation for tuples (e.g. depth-first and left-to-right)?


Solution

  • Yes, the order of evaluation for tuples is guaranteed to be left-to-right (which also implies depth-first, as the value must be fully constructed).

    Unfortunately, this is never stated explicitly anywhere that I can find, but can be inferred from Rust's strong backwards compatibility guarantees. Making a change to evaluation order would likely introduce far too much breakage to ever be seriously considered.

    I'd also expect that the optimizer is allowed to make changes when safe to do so. For example, if the expressions in the tuple have no side effects, then reordering them is invisible to the user.

    See also: