Oh, I think I misread your post. Youâre asking why writing for &elem in ... instead of for elem in ... turns &String into String instead of &&String. As I mentioned above thatâs due to how & works in patterns.
This is analogous to something like
struct Foo<T>(T);
let x = Foo(42);
// x is `Foo<i32>`
let Foo(y) = x;
// y is `i32` and not `Foo<Foo<i32>>
Patterns usually do kind-of âthe oppositeâ of expressions, so we have
let x = &42;
// x is `&i32`
let &y = x;
// y is `i32` and not `&&i32`
Also, as mentioned above, this doesnât actually work for String like that. The assignment let &y = x; copies the value 42 into y.
for loops are similar to let expressions:
struct Foo<T>(T);
let x = vec![Foo(42), Foo(69)];
// x is Vec<Foo<42>>`
for y in x.iter() {
// y is &Foo<42>
}
for &y in x.iter() {
// y is Foo<42>
}
for &Foo(y) in x.iter() {
// y is 42
}
Thereâs also more to pattern than this, in particular you can re-introduce the indirection with something like ref, as in
struct Foo<T>(T);
let x = vec![Foo(42), Foo(69)];
// x is Vec<Foo<42>>`
for &Foo(ref y) in x.iter() {
// y is &42
}
This has the benefit that it avoids the need to copy the type and it also works with something like String again:
struct Foo<T>(T);
let x = vec![Foo("hello".to_string()), Foo("world".to_string())];
// x is Vec<Foo<String>>`
for &Foo(ref y) in x.iter() {
// y is &String
}
/* this wouldnât work:
for &Foo(y) in x.iter() {
// y would have to be String
}
*/
Patterns like &Foo(ref x) had become so common in earlier Rust versions that thereâs a shorter syntax for them
struct Foo<T>(T);
let x = vec![Foo("hello".to_string()), Foo("world".to_string())];
// x is Vec<Foo<String>>`
for &Foo(ref y) in x.iter() {
// y is &String
}
// the above is equivalent to:
for Foo(y) in x.iter() {
// y is &String
}
To clarify, the ref in the above examples does exactly what you seem to have expected & do to, in particular if you try
let list = vec![String::from("Alice"), String::from("Bob"), String::from("Catherine")];
for ref elem in list.iter() {
println!("{}", elem == true) // Type of elem is String
}
youâll see that now elem is &&String. Of course introducing an extra reference level in this situation is relatively useless, youâll probably never see anyone write something like for ref elem in ... ever.