I encountered this strange behaviour when reading this post, and the core question of this post is when you matching (&k, &v) = &(&String, &String)
, k
and v
will get the type String
.
To figure out what's happending, I wote the following test code, and the result is much more shocking and confusing to me:
fn main() {
let x: &(&String, &String) = &(&String::new(), &String::new());
let ref_to_x: &&(&String, &String) = &x;
let ref_ref_to_x: &&&(&String, &String) = &&x;
let ref_ref_ref_to_x: &&&&(&String, &String) = &&&x;
// code snippet 1
let (a, b) = x; // type of a: &&String, type of b: &&String
let (a, b) = ref_to_x; // type of a: &&String, type of b: &&String
let (a, b) = ref_ref_to_x; // type of a: &&String, type of b: &&String
let (a, b) = ref_ref_ref_to_x; // type of a: &&String, type of b: &&String
// code snippet 2
let &(a, b) = x; // type of a: &String, type of b: &String
let &(a, b) = ref_to_x; // type of a: &&String, type of b: &&String
let &(a, b) = ref_ref_to_x; // type of a: &&String, type of b: &&String
let &(a, b) = ref_ref_ref_to_x;// type of a: &&String, type of b: &&String
// code snippet 3
let (&a, &b) = x; // type of a: String, type of b: String
let (&a, &b) = ref_to_x; // type of a: String, type of b: String
let (&a, &b) = ref_ref_to_x; // type of a: String, type of b: String
let (&a, &b) = ref_ref_ref_to_x;// type of a: String, type of b: String
}
The type annotation of a
and b
I added to the end of line is inferred by rust-analyzer
.
Please NOTE, code snippet 3
won't compile due to the error can not move out of xx because it's borrowrd/can not move out of xx which is behind a shared reference
, but I think this doesn't matter (Perhaps I am wrong here, if so, point me out, thanks) cause we are concentrating on the type of a
and b
.
My questions are:
- why do
a
andb
always have the same type even when the RHS have different types(x/ref_to_x/ref_ref_to_x..) in code snippet 1/2/3? - how does this matching happen(a step-by-step matching process would be appreciated) ?
- How can I get the exactly same type inference as
rust-analyzer/rustc
when writing code?
BTW, is this relevant to the rfc 2005 match-ergonomics? I googled a lot and found many people mentioned this in their answer.