Rust 匹配和借用检查器

标签 rust matching borrow-checker

我一直在我的 Rust 程序中遇到一种模式,这种模式总是让我与借用检查器发生冲突。考虑以下玩具示例:

use std::sync::{Arc,RwLock};

pub struct Test {
    thing: i32,
}

pub struct Test2 {
    pub test: Arc<RwLock<Test>>,
    pub those: i32,
}

impl Test {
    pub fn foo(&self) -> Option<i32> {
        Some(3)
    }
}

impl Test2 {
    pub fn bar(&mut self) {
        let mut test_writer = self.test.write().unwrap();

        match test_writer.foo() {
            Some(thing) => {
                self.add(thing);
            },
            None => {}
        }
    }

    pub fn add(&mut self, addme: i32) {
        self.those += addme;
    }
}

这不会编译,因为 Some arm 中的 add 函数试图可变地借用 self,它已经在 match 语句上方被不变地借用以打开读写锁。

我在 Rust 中遇到过几次这种模式,主要是在使用 RwLock 时。我还找到了一个解决方法,即在 match 语句之前引入一个 bool 值,然后更改 Some 臂中的 bool 值,最后引入一个测试match 语句之后的这个 bool 值,用于执行我想在 Some arm 中执行的任何操作。

在我看来,这不是解决问题的方法,我认为在 Rust 中有更惯用的方法来做到这一点——或者以完全不同的方式解决问题——但我找不到它。如果我没记错的话,这个问题与词法借用有关,所以 self 不能在 match 语句的范围内可变地借用。

是否有惯用的 Rust 方法来解决这类问题?

最佳答案

直接使用字段那些,例如自定义类型:

use std::sync::{Arc,RwLock};

pub struct Those(i32);

impl Those {
    fn get(&self) -> i32 {
        self.0
    }

    fn add(&mut self, n: i32) {
        self.0 += n;
    }
}

pub struct Test {
    thing: Those,
}

pub struct Test2 {
    pub test: Arc<RwLock<Test>>,
    pub those: Those,
}

impl Test {
    pub fn foo(&self) -> Option<Those> {
        Some(Those(3))
    }
}

impl Test2 {
    pub fn bar(&mut self) {
        let mut test_writer = self.test.write().unwrap();

        match test_writer.foo() {
            Some(thing) => {
                // call a method add directly on your type to get around the borrow checker
                self.those.add(thing.get());
            },
            None => {}
        }
    }
}

关于Rust 匹配和借用检查器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45505607/

相关文章:

performance - 为什么更新到 Rust 1.38.0 后 Vec::retain 运行速度变慢?

rust - 不能在 mpsc::channel 上使用 Stream::take_while: bool: future 不满足

相关性/匹配值(value)树算法

ios - 快速获取字符串中子字符串的所有范围

rust - 从借用它的循环内部操作对象

rust - 为什么这个 Rust 2018 代码编译时使用 `cargo build` 而不是使用 rustc?

rust - 使用 config-rs 将 TOML 字符串反序列化为枚举

postgresql - 我如何使用 postgres crate 从 PostgreSQL 接收表修改事件?

python - 在 Python 中实现比较类的 OOP 方法

stream - 在多个闭包中表达变量对的生命周期