请考虑以下内容:
struct Str<'a> {
s: &'a str,
}
fn f1<'a>(_: &'a mut Str<'a>) {}
fn f2<'a, 'b>(_: &'a mut Str<'b>) {}
fn main() {
let s = "hello".to_string();
let mut a = Str {
s: &s,
};
f1(&mut a);
// f2(&mut a);
let t: &Str = &a;
}
[f2
使用两个不同的生存期,就像我删除它们时那样,可以正常工作。
[在这一点上,我认为寿命'a
是指&mut a
的寿命,而'b
是指&s
的寿命。
然后我写了f1
,它使用单个生命周期参数,怀疑生命周期'a
指的是&mut a
生命周期和&s
生命周期中的较短者。
但是,此f1
失败,并出现以下错误:
error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
--> src/main.rs:21:19
|
18 | f1(&mut a);
| ------ mutable borrow occurs here
...
21 | let t: &Str = &a;
| ^^
| |
| immutable borrow occurs here
| mutable borrow later used here
该错误使我感到困惑:为什么在调用a
之后仍然借用f1
作为可变的?
为什么会失败,错误消息应该是什么意思?
为什么在调用
a
之后仍将f1
借为可变的?
fn main() {
// scope of s ---\
let s = "hello".to_string(); // |
let mut a = Str { // |
s: &s, // |
}; // |
// |
// f1 borrows a until ---\ |
f1(&mut a); // | |
// but it's used here \ | |
let t: &Str = &a; // X // | |
// X X
}
s
的范围一直到main
的结尾。由于f1
自变量的生命周期注释,可变引用&mut a
的生命周期与s
的范围相关联,这意味着f1
在a
的整个范围内都借用了s
。
这对于不可变的引用不是问题,因为更长的寿命可能被强制转换为较短的寿命;换句话说,不变引用的生存期为covariant。但是mutable引用的生存期是invariant。这意味着它们不能被强制缩短(或更长)的寿命。