Analogy to other kinds of patterns might help making this more intuitive:
Well, actually, as a first (preliminary) step it’s important to realize that
for &item in sn {
println!("{}", *item);
}
stands for something like
for the_item in sn {
let &item = the_item;
println!("{}", *item);
}
and not for something like
for the_item in sn {
let item = &the_item;
println!("{}", *item);
}
Now we can talk about why it makes sense that let &item = the_item;
will remove one layer of reference, not add it; by comparing to similar expressions with tuples and arrays:
The most familiar/straightforward kind of pattern matching in let
for many people is probably something like
let tuple = (1, 2);
let (a, b) = tuple;
Here, the “pattern” (a, b)
in a let
splits up the tuple
back into its two parts. The same thing works also for arrays:
let array = [1, 2];
let [a, b] = array; // a and b are `i32`s again
There is also the option to have an array with only a single element
let array = [1];
let [a] = array; // a is an `i32` again
and with this example, we’re already very close to how things work with references, too. Both single-element arrays and references only contain a single element. The [1]
expression (and the right-hand-side of the “=
” in a let
is always an expression) places the 1
into an array, and the [a]
pattern (and the left-hand-side of the “=
” in a let
is always a pattern) takes the value back out of the array. And analogously, &1
in an expression vs. &a
in a pattern puts either takes a reference to the value, or retrieves the value from behind a reference, respectively (the latter is also known as dereferencing).
let reference = &1;
let &a = reference; // a is an `i32` again
So in effect,
let &a = reference;
dereferences, so on a reference: &i32
, it does the same as
let a = *reference;