使用 Rc<RefCell<T>> 进行匹配

10

考虑下面的代码 - 编译并运行正常:

use std::rc::Rc;
use std::cell::RefCell;
use crate::Foo::{Something, Nothing};

enum Foo {
    Nothing,
    Something(i32),
}

fn main() {
    let wrapped = Rc::new(RefCell::new(Foo::Nothing));
    //....

    match *wrapped.borrow() {
        Something(x) => println!("{}", x),
        Nothing => println!("Nothing"),
    };        
}

现在我想要匹配两个包装过的值,而不仅仅是一个:
use std::rc::Rc;
use std::cell::RefCell;
use crate::Foo::{Something, Nothing};

enum Foo {
    Nothing,
    Something(i32),
}

fn main() {
    let wrapped1 = Rc::new(RefCell::new(Foo::Nothing));
    let wrapped2 = Rc::new(RefCell::new(Foo::Nothing));
    //....

    match (*wrapped1.borrow(), *wrapped2.borrow()) {
        (Something(x), Something(y)) => println!("{}, {}", x, y),
        _ => println!("Nothing"),
    };        
}

现在这会导致编译错误:

error[E0507]: cannot move out of dereference of `std::cell::Ref<'_, Foo>`
  --> src\main.rs:16:12
   |
16 |     match (*wrapped1.borrow(), *wrapped2.borrow()) {
   |            ^^^^^^^^^^^^^^^^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait

error[E0507]: cannot move out of dereference of `std::cell::Ref<'_, Foo>`
  --> src\main.rs:16:32
   |
16 |     match (*wrapped1.borrow(), *wrapped2.borrow()) {
   |                                ^^^^^^^^^^^^^^^^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait

我不太理解这两个示例的语义基本区别。为什么会发生这种情况,如何才能使第二个代码片段正常工作?

1个回答

13
    match (*wrapped1.borrow(), *wrapped2.borrow()) {

您在此处即席创建了一个元组。值正在移动到新创建的元组中。这样做是可行的:

use std::rc::Rc;
use std::cell::RefCell;
use crate::Foo::Something;

enum Foo {
    Nothing,
    Something(i32),
}

fn main() {
    let wrapped1 = Rc::new(RefCell::new(Foo::Nothing));
    let wrapped2 = Rc::new(RefCell::new(Foo::Nothing));

    match (&*wrapped1.borrow(), &*wrapped2.borrow()) {
        (Something(x), Something(y)) => println!("{}, {}", x, y),
        _ => println!("Nothing"),
    };        
}

2
哇,好的,现在所有的一切都清楚了,多亏了这个答案和这个链接:https://stackoverflow.com/a/66494730/34871。所以:borrow返回一个不可变的锁守卫 “Ref<T>”,如果存在任何可变借用,则可能会出现 panic,并且如果尚未被丢弃,则将使可变借用 panic;' * '解引用为 'T',但尚未移出,因为我们立即使用 '&' 引用。通过这种 &*x.borrow() 语法,Ref<T> 只存在于匹配范围内,因此在 match 后稍后安全地获取可变引用(将 Ref 保存在变量中需要显式丢弃)。 - vincent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接