&Vec<i32> vs &[i32] vs [i32]

You misunderstand the precedence here. A simple rule suffices to remember this and similar case: in Rust, all postfix operators have higher precedence than all prefix operators. Therefore, &v[2..4] is not equivalent to (&v)[2..4], but to &(v[2..4]). Therefore, if you want to split let t = &v[2..4] into two lines, the accurate way to do so is not

    let s = &v;
    let t = s[2..4];

but rather

    let s = v[2..4];
    let t = &s;

@jumpnbrownweasel already explained one reason this doesn't compile — you can't put a dynamically-sized value on the stack. But another scenario with the same operators wouldn't compile either, for a different but related reason:

    let v: Vec<String> = vec![String::new(), String::new()];
    let s = v[0];

This too would fail, even though s is of the perfectly good type String, because it is trying to move the String out of the Vec<String>, leaving it with an unfilled gap, which is not allowed. The theme in both these cases is that v[0] and v[2..4] refers to a place in memory — a portion of the contents of the Vec. When you take a reference to a place, that is different than writing the place expression by itself, which moves or copies out of the place (or fails to compile if that is not possible).

So, there is a sense in which &(expr)[] is acting as a single operator — you can't separate its parts and get the same result.

9 Likes