To match a struct while preventing a move, I want to use a reference to do the match. So the following code will do the job:
struct Foo(i32);
fn main() {
let x = Foo(1);
match &x {
ref a => println!("hello"),
}
println!("{}", x.0);
}
But I am surprised to find that the following code also works, which actually matched a struct (x) with a reference (ref a). But, shouldn't it be a type mismatch here?
struct Foo(i32);
fn main() {
let x = Foo(1);
match x {
ref a => println!("hello")
}
println!("{}", x.0);
}
ref is not a normal part of the pattern that "strips away" something from the value, but is a modifier of the name binding, like mut. It instructs the name to bind to a reference to the value instead of the value directly.
Let's see what type a has in each case:
match &x {
ref a => {
let () = a;
}
}
match x {
ref b => {
let () = b;
}
}
The let () = a; is a trick to find out the type of a. And indeed the compiler tells us:
|
7 | let () = a;
| ^^ expected &&Foo, found ()
[...]
|
12 | let () = b;
| ^^ expected &Foo, found ()
So in the first case, we have reference to a reference, namely &&Foo. This is because we're matching on the expression &x (type: &Foo) and then tell the compiler to bind the name "by reference".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With