rust - 我如何告诉编译器在不删除整个结构的情况下释放结构中的借用?

标签 rust borrow-checker

我有以下结构表示数字计算的计划:

pub struct NfftPlan<'a> {
    x: Option<&'a [f64]>,
    f_hat: Option<&'a [Complex64]>,
    // ...
}

它有一个set_f_hat方法:

pub fn set_f_hat(&mut self, f_hat: &'a [Complex64]) {
    self.f_hat = Some(f_hat);
}

和一个执行方法:

pub fn execute(&self) -> Vec<Complex64>

不变地使用 f_hat

我想按以下方式使用它:

let mut f_hat = vec![1,2,3,4];
let plan = NfftPlan::new()
plan.set_f_hat(&f_hat);
plan.execute();
f_hat[0] = 3; // Change f_hat to a new value
plan.execute(); //New computation

这失败了,因为我无法在 plan 仍然存在的情况下改变 f_hat。 有没有办法让 plan 释放对 f_hat 的借用,这样我就可以改变 f_hat 向量? 像这样:

releasedata(&self) {
    self.f_hat = None
} //Now the compiler forgets that plan would hold an borrow to f_hat

我知道 Rust 不允许我在借用向量时更改向量,在这种情况下,通过 NfftPlan 结构中的 f_hat 引用。 我想要一种方法告诉编译器在 NfftPlan 结构中删除对向量的引用,而不删除整个结构。

最佳答案

说明

How can I tell the compiler to release a borrow

你不能,句号。这不是您“告诉”编译器的事情,编译器什么都知道。您只能完全停止使用该引用。

without dropping the entire struct

丢弃 不会清除借用,只有不再使用的借用才会清除,这可能会因丢弃而发生。

f_hat[0] = 3; // Change f_hat to a new value
plan.execute(); //New computation

正是 Rust 试图阻止的代码类型之一。 plan.execute() 应该返回一个不同的值一点也不明显,因为一些明显无关的值发生了变化。

解决方案

在类型系统中编码

我会构建我的类型以反射(reflect)它们需要如何使用,创建一次性值,这些值只有在所有内容组合在一起后才能执行。这意味着借用 f_mut 的结构一完成就被丢弃;请注意这是如何完全删除 Option 的:

fn main() {
    let mut f_hat = 42;

    let plan = Plan::default();
    plan.set_f_hat(&f_hat).execute();

    f_hat = 3;
    plan.set_f_hat(&f_hat).execute();
}

#[derive(Debug, Default)]
struct Plan<'a> {
    x: Option<&'a i32>,
}

impl<'a> Plan<'a> {
    fn set_f_hat(&self, f_hat: &'a i32) -> PlanPlus<'a> {
        PlanPlus { x: self.x, f_hat }
    }
}

#[derive(Debug)]
struct PlanPlus<'a> {
    x: Option<&'a i32>,
    f_hat: &'a i32,
}

impl<'a> PlanPlus<'a> {
    fn execute(&self) {}
}

使用内部可变性和引用计数

use std::{cell::Cell, rc::Rc};

#[derive(Debug, Default)]
struct Plan<'a> {
    x: Option<&'a i32>,
    f_hat: Option<Rc<Cell<i32>>>,
}

impl<'a> Plan<'a> {
    fn set_f_hat(&mut self, f_hat: Rc<Cell<i32>>) {
        self.f_hat = Some(f_hat);
    }
    fn execute(&self) {}
}

fn main() {
    let f_hat = Rc::new(Cell::new(42));

    let mut plan = Plan::default();
    plan.set_f_hat(f_hat.clone());
    plan.execute();

    f_hat.set(3);
    plan.execute();
}

识别成员是可变的

#[derive(Debug, Default)]
struct Plan<'a> {
    x: Option<&'a i32>,
    f_hat: Option<&'a mut i32>,
}

impl<'a> Plan<'a> {
    fn f_hat(&mut self) -> &mut Option<&'a mut i32> {
        &mut self.f_hat
    }

    fn execute(&self) {}
}

fn main() {
    let mut f_hat = 42;

    let mut plan = Plan::default();
    *plan.f_hat() = Some(&mut f_hat);
    plan.execute();
    **plan.f_hat().as_mut().unwrap() = 3;
    plan.execute();
}

另见:

关于rust - 我如何告诉编译器在不删除整个结构的情况下释放结构中的借用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57694567/

相关文章:

sorting - 使用带有 seq::index::sample 的排序时出现 Rust 错误

rust - 为什么解构借用的枚举需要取消引用其字段?

syntax - 从函数的堆栈返回对 Path 的引用是如何工作的?

rust - 如何借用结构的 curry 函数字段?

rust - 为什么 by_ref().take() 的用法在 Iterator 和 Read 特征之间不同?

process - 执行任何 bash 命令,立即获取 stdout/stderr 的结果并使用 stdin

rust - 为什么 Command.output() 执行有时会为 status.code() 返回 None

rust - 为什么我不能将这个尾递归函数转换为 Rust 中的迭代函数?

rust - 即使 NLL 打开,循环中的双可变借用错误也会发生

rust - 如何将迭代器的每个元素重复 n 次?