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.