As pointed out in the comments, you're making a new variable called s
. Up to renaming, your code is equivalent to
let mut v : Vec<u8> = Vec::new();
v.push(0);
v.push(1);
v.push(2);
let s = &v;
print!("{:?} - ", s); // will output "[0, 1, 2]"
let my_unrelated_s_variable = &v[1..];
println!("{:?}", my_unrelated_s_variable); // will screen "[1, 2]"
The two s
you declared are, as far as the Rust compiler is concerned, unrelated variables. In fact, we could even give the second one a different type.
let s = &v;
let s = 42; // This one's an integer, but it's fine
This sort of shadowing is very common in Rust when we want to augment a particular value but want to respect immutability, as it guarantees we aren't actually changing anything in memory while allowing us the convenience of reusing variable names. For example, I often find myself doing things like this.
fn example(input: &str) {
let input = some_complicated_parsing_step(input)?;
...
}
The argument input
is a string, and I want to convert it to something (maybe parse it as JSON, maybe read an integer from it, etc.). Once I do that, I have no use for the original string anymore, and it's reasonable to call the result of parsing input
, as it is still the input I was given, just in a different form now.