我在下面的代码中生成了注释中标记的错误消息。我想我理解这个信息:我想借父母两次:一次是为了找到它的孩子,一次是作为孩子的一个参数(并且错误中的可变/不可变的词是不相关的)。我必须证明Child
在修改Parent
时不会消失。但我不知道该怎么做。我可以Rc<Child>
所有东西,但接缝浪费,所以我希望增加一些生命周期就可以了。
struct Parent {
used: i32,
child: Child,
}
struct Child {
dummy: i32,
}
impl Child {
fn use_parent(&mut self, parent: &mut Parent) {
// use both child and parent
parent.used += self.dummy;
self.dummy += 1;
}
}
fn main() {
let parent = Parent {
used: 0,
child: Child {
dummy: 1
}
};
//Error: cannot borrow immutable local variable `parent` as mutable
parent.child.use_parent(&mut parent);
}
答案 0 :(得分:1)
并且错误中的可变/不可变单词不相关
我不确定你为什么这么想。在Rust中,可变性非常重要非常重要例如,虽然允许同时多次引用不可变数据,但一次只允许对可变数据进行一次引用。
首先,您需要修复parent
的可变性:
let mut parent = // ...
然后,您将从该行获得错误:
parent.child.use_parent(&mut parent);
当您运行此行时,您隐含地可变地借用parent
和child
。这样做是为了让您拨打use_parent
,这需要&mut self
。
但是,你也试图获得第二个可变引用作为参数!这是禁忌,因为如果您被允许有多个别名可变引用,编译器将无法跟踪它并确保您不会破坏内存安全保证
假设我删除了行
self.dummy+=1;
,因此只有一个可变别名 - 我可以让它工作吗?
让我们看一下函数签名的一些变体
fn use_parent(&self, parent: &mut Parent)
// cannot borrow `parent` as mutable because `parent.child` is also borrowed as immutable
fn use_parent(&mut self, parent: &Parent)
// cannot borrow `parent` as immutable because `parent.child` is also borrowed as mutable
fn use_parent(&self, parent: &Parent)
// OK
正如我前面提到的,如果你有一个可变的引用,你就不允许任何对同一件事的其他引用(可变或不可用)。
另外,请注意无关紧要该方法的主体是什么! Rust只检查被调用函数的签名,以验证借用某些东西是否安全。
那你怎么试着解决你的问题呢?最终,您正在尝试做一些编译器难以证明安全的事情。您需要一个可变链接的图形。我强烈建议阅读module documentation for Rc,其中有一个确切的亲子关系的例子。
答案 1 :(得分:1)
您收到错误消息的原因不同。您有一个不可变的变量parent
,并且正在尝试为其创建&mut
。修复你的问题
let mut parent = Parent {
used: 0,
child: Child {
dummy: 1
}
};
parent.child.use_parent(&mut parent);
和相应的错误
<anon>:31:34: 31:40 error: cannot borrow `parent` as mutable more than once at a time
<anon>:31 parent.child.use_parent(&mut parent);
^~~~~~
<anon>:31:5: 31:17 note: previous borrow of `parent.child` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `parent.child` until the borrow ends
<anon>:31 parent.child.use_parent(&mut parent);
^~~~~~~~~~~~
<anon>:31:41: 31:41 note: previous borrow ends here
<anon>:31 parent.child.use_parent(&mut parent);
^
你几乎得出了正确的结论。
我必须证明Child在修改Parent
时不会消失
不完全。您必须证明您的孩子永远不会有两个&mut
或一个&mut
和一个&
。如果你的父母有&mut
,你可以用它来给孩子一个&mut
。因此,如果您的父母有&mut
,孩子有&mut
,那么您可以为孩子提供两个&mut
。
我看到的唯一解决方案是将use
功能移至Parent
类型,然后通过child
访问self
。
impl Parent {
fn use_parent(&mut self) {
// use both child and parent
self.used += self.child.dummy;
self.child.dummy += 1;
}
}
发表评论:
不幸的是,该解决方案适用于此简化问题,但不适用于我的实际问题。父有一个孩子的矢量,可能有深层嵌套的孩子。我不能只说self.child
由于你不应该修改你的向量(并且不能,Rust保护你),因为这会使对子进程的引用无效,你可以将这些部分传递给你需要的函数,但没有任何部分是孩子的直接父母。
impl Child {
fn use_parent(&mut self, used: &mut i32) {
// use both child and parent
*used += self.dummy;
self.dummy += 1;
}
}
fn main() {
let mut parent = Parent {
used: 0,
child: Child {
dummy: 1
}
};
// although both point to elements of the same structure
// it is guaranteed at compile-time that they point to
// non-overlapping parts
let child = &mut parent.child;
let used = &mut parent.used;
child.use_parent(used);
}
不幸的是,我没有看到证明use_parent
的参数指向同一Parent
个对象的部分的方法。也许这可以用一生来完成,我不确定,但我会对此毫无兴趣。注意:Rc
有同样的问题。