尝试编译这个程序我被卡在借用检查器上:
use std::collections::BTreeMap;
type Object<'a> = BTreeMap<&'a str, i32>;
struct Root<'a>(Object<'a>);
struct Sub<'a>(&'a mut Object<'a>, &'a str);
impl<'a> Root<'a> {
fn borrow_mut(&'a mut self, data: &'a str) -> Sub<'a> {
Sub(&mut self.0, data)
}
fn borrow(&self) {
println!("{:?}", self.0);
}
}
fn main() {
let mut me = Root(Object::new());
{
me.borrow_mut("data!");
}
me.borrow();
}
我明白了:
error[E0502]: cannot borrow `me` as immutable because it is also borrowed as mutable
--> src/main.rs:24:5
|
22 | me.borrow_mut("data!");
| -- mutable borrow occurs here
23 | }
24 | me.borrow();
| ^^ immutable borrow occurs here
25 | }
| - mutable borrow ends here
看起来可变借用应该在me.borrow()
之前结束,但是借用检查器坚持在main
结束时结束。
快速解释我想要完成的事情:
答案 0 :(得分:8)
你正在与一生的问题发生冲突。
您的计划中有多个不同的生命周期:
type Object<'a> = BTreeMap<&'a str, i32>;
=&gt;这是一个&'a mut Object<'a>
=&gt;这里最多有两个struct Sub<'a>(&'a mut Object<'a>, &'a str);
=&gt;这里最多有三个显然,Object<'a>
的引用没有理由与&str
内的BTreeMap
具有相同的生命周期。但是,您告诉编译器您希望两个生命周期都相同!
当你写:
struct Sub<'a>(&'a mut Object<'a>, &'a str);
你告诉编译器:
&str
内BTreeMap
Object<'_>
&str
Object<'_>
的有效期
都是一样的。
您对要求过度约束;因此,没有解决方案可以满足他们。
增加一个自由度就足够了!我们只会使Object<'_>
的引用的生命周期与那些浮动的&str
的生命周期不同:
struct Sub<'a, 'b: 'a>(&'a mut Object<'b>, &'b str);
impl<'b> Root<'b> {
fn borrow_mut<'a>(&'a mut self, data: &'b str) -> Sub<'a, 'b> {
Sub(&mut self.0, data)
}
fn borrow(&self) {
println!("{:?}", self.0);
}
}
请注意细微的'b: 'a
:
Object<'b>
包含对其生命周期为'b
Object<'b>
(表示为'a
)的引用的生命周期必须比'b
更短(否则你会引用死的东西?)因此,我们说'b
比'a
更长'b: 'a
。
就是这样。简单地放宽要求允许编译器允许您的代码进行编译。
请注意,一般情况下,如果您发现自己写的是&'a &'a str
,那么您做错了。如果您考虑一下,您会意识到,为了创建对某事物的引用,它必须首先 。因此,对象必然的引用具有比对象本身更短的生命周期(稍微有点)。