此代码未能通过可怕的借用检查器 (playground):
struct Data {
a: i32,
b: i32,
c: i32,
}
impl Data {
fn reference_to_a(&mut self) -> &i32 {
self.c = 1;
&self.a
}
fn get_b(&self) -> i32 {
self.b
}
}
fn main() {
let mut dat = Data{ a: 1, b: 2, c: 3 };
let aref = dat.reference_to_a();
println!("{}", dat.get_b());
}
由于实现了非词法生命周期,因此需要触发错误:
fn main() {
let mut dat = Data { a: 1, b: 2, c: 3 };
let aref = dat.reference_to_a();
let b = dat.get_b();
println!("{:?}, {}", aref, b);
}
错误:
error[E0502]: cannot borrow `dat` as immutable because it is also borrowed as mutable
--> <anon>:19:20
|
18 | let aref = dat.reference_to_a();
| --- mutable borrow occurs here
19 | println!("{}", dat.get_b());
| ^^^ immutable borrow occurs here
20 | }
| - mutable borrow ends here
这是为什么?我本以为 dat
的可变借用在 reference_to_a()
返回时被转换为不可变借用,因为该函数只返回一个不可变引用。借用检查器还不够聪明吗?这是有计划的吗?有解决办法吗?
最佳答案
生命周期与引用是否可变无关。通过代码工作:
fn reference_to_a(&mut self) -> &i32
虽然省略了生命周期,但这等同于:
fn reference_to_a<'a>(&'a mut self) -> &'a i32
即输入和输出生命周期相同。这是为这样的函数分配生命周期的唯一方法(除非它返回对全局数据的 &'static
引用),因为您不能从无到有地弥补输出生命周期。
这意味着,如果您通过将返回值保存在变量中来保持其事件状态,您也将保持 &mut self
事件状态。
另一种思考方式是 &i32
是 &mut self
的子借用,因此仅在到期之前有效。
正如@aSpex 指出的那样,这是 covered in the nomicon .
关于rust - 为什么可变的 self 借用不会变成不可变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51831126/