fn main() {
struct Foo<'a, T> {
a: &'a mut T,
}
let p1 = 1;
let mut p2 = &p1;
{
let p3 = 2;
let mut p4 = &p3;
let mut f = Foo {
a: &mut p4,
};
f.a = &mut p2;
println!("{}", f.a);
}
println!("{}", p2);
}
运行此程序时,遇到如下错误:
第一个
这是我第一个问题:为什么会存在这些错误?
如果我注解最后一行,例如:
fn main() {
struct Foo<'a, T> {
a: &'a mut T,
}
let p1 = 1;
let mut p2 = &p1;
{
let p3 = 2;
let mut p4 = &p3;
let mut f = Foo {
a: &mut p4,
};
f.a = &mut p2;
println!("{}", f.a);
}
// println!("{}", p2);
}
通过引用rustonomicon,
f.a = &mut p2;
&'a mut T在'a上是协变的,在T上是不变的,它应该编译不成功。但是编译成功了,为什么?
如果我注解最后一行,它应该编译不成功。
1条答案
按热度按时间tf7tbtn21#
问题的核心是
f
有一个固定类型Foo<'a, &'b i32>
,并且根据可变引用的方差规则,&'b i32
是不变的,因此'b
是不变的。但是,
f
通过p2
和p4
与T
一起作为两个独立的生存期使用。编译器如何选择?它不能将p2
使用的生存期缩短为p4
使用的生存期。因为p2
可以被修改以引用更短寿命的某个东西(考虑一下,如果在将f.a
赋值给&mut p2
之后立即添加*f.a = &p3;
,将会发生什么情况)。唯一的选择是将p4
使用的生存期扩展到与p2
匹配。由于
p4
必须与p2
的生存期匹配,因此来自p3
的赋值现在太短了,所以您会得到所看到的错误。第二个示例有效,因为
p2
使用的生存期不会在内部块中的println!
之后延长,因此p3
可以满足该生存期。