fn main() {
let v = &vec![("1".to_string(), "2".to_string()), ("1".to_string(), "2".to_string())];
for (a,b) in v {
let z: () = (a, b);
}
for c in v {
let z: () = c;
}
}
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:4:21
|
4 | let z: () = (a, b);
| -- ^^^^^^ expected `()`, found tuple
| |
| expected due to this
|
= note: expected unit type `()`
found tuple `(&String, &String)`
error[E0308]: mismatched types
--> src/main.rs:7:21
|
7 | let z: () = c;
| -- ^ expected `()`, found `&(String, String)`
| |
| expected due to this
|
= note: expected unit type `()`
found reference `&(String, String)`
error: aborting due to 2 previous errors
How come when destructured, the tuple becomes (&String, &String) ?
Not trying to be aggressive but it seems that match ergonomics would be. c -> &(String, String) and thus to extract the value behind the reference &c -> (String, String)
I get that.
but how come (a, b) which is c &(String, String) being destructured equals (&String, &String)
Basically how come &(String, String) == (&String, &String) ?
Sorry if I am too dumb to understand this. Bear with me
Perhaps try to read the article I linked from the beginning, (i. e. including the part above what I linked to), it sets it up quite well. You kind-of need to understand &-patterns and ref patterns to really understand what's happening and why.
One important insight is that without match ergonomics, your code wouldn't compile at all since you're matching a reference against a pattern for a tuple. Instead of a compilation error, the pattern (a, b) in this case gets a new meaning and "desugars" to &(ref a, ref b). There's no logical reason behind why it should do so, it's just an extra rule that's often convenient in practice.
I am back ...was testing in playground and before seeing your solution I tried:
let v = &vec![("1".to_string(), "2".to_string()), ("1".to_string(), "2".to_string())];
for (ref a, ref b) in v {
let c:() = (a, b);
}
|
4 | let c:() = (a, b);
| -- ^^^^^^ expected `()`, found tuple
| |
| expected due to this
|
= note: expected unit type `()`
found tuple `(&String, &String)`
Thank you. The fact that you mentioned ref put me on the right track. So It is thanks to you and you got my vote!
One way to think of the match ergonomics here is by analogy to for loops with containers.
If you for x in vec {, then x is a T.
If you for x in &vec {, then x is a &T.
If you for x in &mut vec {, then x is a &mut T.
If you match (a, b) { (x, y) =>, then x, y are T, U.
If you match &(a, b) { (x, y) =>, then x, y are &T, &U.
If you match &mut (a, b) { (x, y) =>, then x, y are &mut T, &mut U.
As demonstrated by the question, it's also useful when destructuring references, simply because it's clearer. Pattern matching "ergonomics" is a misfeature in my opinion. I suggest turning on the pattern_type_mismatch lint so that references stay references and values stay values.