Does non-matching arm take the owner of a variable in a “match” statement in Rust?

耗尽温柔 提交于 2021-02-16 21:30:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!