在 Rust 中,编译器在评估泛型参数(包括泛型生命周期参数)时会在函数调用边界处停止。在您的情况 1 中,您正在调用一个方法:
fn get_qux(&mut self) -> &mut Qux {
&mut self.qux
}
该函数表明all of self
将被可变地借用,并且返回的引用将一直存在self
将要。在此期间,不得对 self 或其组件进行其他借用(可变或不变)。
在你的第二种情况下,你组成了一个全新的Qux
与您的结构没有任何附件。这不是一个很好的例子,因为它具有非常不同的含义。如果这个案例适合你,你应该这样做。但是,您不会修改与情况 1 相同的内容。
在第三种情况下,您可以避免函数调用。这意味着编译器有更多关于到底借用了什么的信息。具体可以看出self.qux
根本不与self.bars
,所以没有错误。
您可以通过添加新范围来使原始示例正常工作:
fn run(&mut self) {
{
let mut qux = self.get_qux();
let qux_mut = &mut qux;
qux_mut.baz = true;
}
for bar in &self.bars {
println!("{:?}", bar);
}
}
在这里,人为范围清楚地定义了可变借用的结束位置。一旦借用结束,其他项目就可以进行新的借用。
如果您需要修改qux
在循环内部,那么您需要遵循第三种模式:
let mut qux = &mut self.qux;
for bar in &self.bars {
qux.baz = ! qux.baz;
println!("{:?}", bar);
}
或者更简单:
for bar in &self.bars {
self.qux.baz = ! self.qux.baz;
println!("{:?}", bar);
}
很多时候,您可以重构代码来创建包含信息的新结构,并封装一个很好的突变边界来制作这样的代码。