Why does matching on a tuple of dereferenced references not work while dereferencing non-tuples does?

百般思念 提交于 2020-01-05 07:44:20

问题


I'm trying to sort a Vec of enums. Please ignore the sorting mechanism itself, this is just a stripped-down example.

use std::cmp::Ordering;

enum MyEnum {
    Option1,
    Option2,
}

fn main() {
    let mut my_list: Vec<MyEnum> = vec![MyEnum::Option1, MyEnum::Option2, MyEnum::Option1];

    // (1) - doesn't work
    my_list.sort_unstable_by(|a, b| match (*a, *b) {
        (MyEnum::Option1, MyEnum::Option1) => Ordering::Equal,
        (MyEnum::Option1, MyEnum::Option2) => Ordering::Less,
        _  => Ordering::Greater
    });
}

I get the following error:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:12:44
   |
12 |     my_list.sort_unstable_by(|a, b| match (*a, *b) {
   |                                            ^^ cannot move out of borrowed content

The following two variants work:

// (2)
my_list.sort_unstable_by(|a, _b| match *a {
    MyEnum::Option1 => Ordering::Less,
    MyEnum::Option2 => Ordering::Greater
});

// (3)
my_list.sort_unstable_by(|a, b| match (a, b) {
    (&MyEnum::Option1, &MyEnum::Option1) => Ordering::Equal,
    (&MyEnum::Option1, &MyEnum::Option2) => Ordering::Less,
    _  => Ordering::Greater
});

When I want to match a plain reference, I can dereference it (variant 2); why doesn't this work inside the tuple in variant 1?

I understand why 3 works, but struggle with understanding where exactly a move happens in 1 and how to do it differently.


回答1:


where exactly a move happens

A move happens where the compiler is pointing — *a. You are moving the contents of a into a brand-new tuple. You can't do that, so the compiler gives an error.

The ability to "dereference" the matched variable without really dereferencing it is some syntactic goodness provided by the compiler, but it's very limited. It doesn't "see into" the expression, it only looks at some select syntax constructions and knows to ignore them.

It's possible that the compiler could be enhanced to see these cases, but presumably the cost/benefit tradeoff isn't favorable at this point in time.

See also:

  • Is there any difference between matching on a reference to a pattern or a dereferenced value?
  • How can I use match on a pair of borrowed values without copying them?
  • Matching on a reference to an enum


来源:https://stackoverflow.com/questions/48044295/why-does-matching-on-a-tuple-of-dereferenced-references-not-work-while-dereferen

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