By default, match statements consume all they can, which can sometimes be a problem, when you don’t really need the value to be moved and owned.
i.e. in this piece of code
match msg {
x @ Message::World { id, .. } => println!("{x:?} {id}"),
x => println!("{x:?}"),
}
ownership of the enum msg: Message is moved into the first arm and msg will be dropped after you destructure it and extract your id. This means msg is no longer available in other match arms.
This doesn't cause a problem when your enum only has one variant, because the second match arm is unreachable, but when you add the Hello variant to the Message enum, the compiler will complain about a value being used after it's moved.
One possible solution is to match msg by reference rather than take ownership, i.e.
match msg {
ref x @ Message::World { id, .. } => println!("{x:?} {id}"),
ref x @ Message::Hello { a, .. } => println!("{x:?} {a}"),
}
Another would be derive Copy and Clone on your enum, which would allow Rust to make a copy of msg and take ownership of the copy.
It seems that with an irrefutable pattern, the compiler does a partial move, but with a refutable pattern it doesn't. Not sure why, maybe someone with more compiler knowledge can explain. With a partial move, only the id is copied out and there's no problem accessing the enum afterwards, but without a partial move it's a bit like both sides of the @ are trying to take ownership of the whole struct and that's not allowed.
fn main() {
if let e @ E::A(s) = { E::A(String::new()) } {}
}
enum E {
A(String),
B,
}
error[E0382]: use of moved value
--> src/main.rs:2:21
|
2 | if let e @ E::A(s) = { E::A(String::new()) } {}
| - ^ ----------------------- move occurs because value has type `E`, which does not implement the `Copy` trait
| | |
| | value used here after move
| value moved here
vs
fn main() {
if let e @ E::A(s) = { E::A(String::new()) } {}
}
enum E {
A(String),
}
error[E0382]: use of partially moved value
--> src/main.rs:2:12
|
2 | if let e @ E::A(s) = { E::A(String::new()) } {}
| ^ - value partially moved here
| |
| value used here after partial move