Rust 如何告诉编译器在不删除整个结构的情况下在结构中释放借用?
我有以下结构,它表示数值计算的计划:Rust 如何告诉编译器在不删除整个结构的情况下在结构中释放借用?,rust,borrow-checker,Rust,Borrow Checker,我有以下结构,它表示数值计算的计划: pub struct NfftPlan<'a> { x: Option<&'a [f64]>, f_hat: Option<&'a [Complex64]>, // ... } 以及执行方法: 这失败了,因为我不能在计划仍然存在的情况下改变它。 有没有一种方法可以让我们发布借来的f_-hat,让我们变异f_-hat向量? 大概是这样的: releasedata(&self)
pub struct NfftPlan<'a> {
x: Option<&'a [f64]>,
f_hat: Option<&'a [Complex64]>,
// ...
}
以及执行方法:
这失败了,因为我不能在计划仍然存在的情况下改变它。
有没有一种方法可以让我们发布借来的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结构中向量的引用。解释
我如何告诉编译器释放一个借阅
你不能,句号。这不是你告诉编译器的,编译器知道一切。您只能完全停止使用引用
不删除整个结构
丢弃不会清除借出,只有不再使用的借出才会清除,这可能发生在丢弃过程中
这正是Rust试图防止的代码类型之一。plan.execute应该返回不同的值,这一点并不明显,因为某些明显不相关的值已更改
解决
在类型系统中对其进行编码
我会构建我的类型,以反映它们需要如何使用,创建一次性值,只有在所有内容组合在一起后才能执行。这意味着借用f_mut的结构一完成就被删除;请注意,这将完全删除该选项:
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) {}
}
使用内部可变性和引用计数
认识到成员是可变的
另见:
很难回答你的问题,因为它没有包含一个。我们无法说出代码中存在哪些板条箱及其版本、类型、特征、字段等。如果您试图重现您的错误(如果可能的话),或者在全新的货运项目中,那么我们将更容易帮助您,然后您的问题将包括附加信息。您可以使用以下方法减少在此处发布的原始代码。谢谢请粘贴您得到的准确完整的错误-这将帮助我们了解问题所在,以便我们能够提供最好的帮助。有时,试图解释错误消息是很棘手的,而这实际上是错误消息的另一部分,这很重要。我确切地知道我的代码不起作用的原因。Rust不允许我更改向量,因为存在对它的引用。我的问题是如何删除这些对编译器透明的引用这解决了我的特殊问题。但更一般地说,我可能需要两个值x和f_hat,这需要昂贵的预计算。一个或多个结构如何表示这一点。当我改变x时,我不想失去f_帽的预计算功能,也不想失去它。@Unlikus遵循同样的模式。有一个x的结构和从中计算出的任何值,一个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
releasedata(&self) {
self.f_hat = None
} //Now the compiler forgets that plan would hold an borrow to f_hat
f_hat[0] = 3; // Change f_hat to a new value
plan.execute(); //New computation
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();
}