问题
I'm new to Rust. Below is my testing.
#[derive(Debug)]
enum Food {
Cake,
Pizza,
Salad,
}
#[derive(Debug)]
struct Bag {
food: Food
}
fn main() {
let bag = Bag { food: Food::Cake };
match bag.food {
Food::Cake => println!("I got cake"),
x => println!("I got {:?}", x)
}
println!("{:?}", bag);
}
When I run it, I got an error.
error[E0382]: borrow of moved value: `bag`
--> src\main.rs:20:22
|
17 | x => println!("I got {:?}", x)
| - value moved here
...
20 | println!("{:?}", bag);
| ^^^ value borrowed here after partial move
|
= note: move occurs because `bag.food` has type `Food`, which does not implement the `Copy` trait
It's clear that bag.food
will not match x
arm in the code. Why a move happens there?
回答1:
It doesn't matter that the x
branch is not taken at runtime because whether a match
takes ownership of its argument does not depend on which branch of the match
will actually be taken. Much like in this code (also see this followup question):
let foo = "blargh".to_owned();
if false {
let _bar = foo;
}
println!("{}", foo); // error[E0382]: borrow of moved value: `foo`
foo
is never actually moved, but that doesn't make any difference to whether it is valid after the if
(it isn't).
The match
in the question takes ownership of bag.food
(invalidating bag
) because it has a branch that takes ownership. If you want that particular branch to not take ownership, you can use a ref
pattern to borrow instead:
match bag.food {
Food::Cake => println!("I got cake"),
ref x => println!("I got {:?}", x)
}
Alternatively, since Rust 1.26 the compiler knows how to bind value patterns (such as Food::Cake
) to references (such as &bag.food
), so you can write:
match &bag.food {
Food::Cake => println!("I got cake"),
x => println!("I got {:?}", x)
}
In this case Food::Cake
matches the value, but x
matches and is bound to the reference, so it does the same thing as the previous snippet with ref
. (You may see this referred to as "default binding modes" or "match ergonomics".)
来源:https://stackoverflow.com/questions/59215169/does-non-matching-arm-take-the-owner-of-a-variable-in-a-match-statement-in-rus