这里有两个问题。首先是您过度指定了生命周期,造成了编译器无法处理的情况。
fn f0<'a>(t0: &'a mut MyItr<'a>, t1: &'a mut MyItr<'a>, i: &'a i32)
您已经告诉编译器所有参数都必须是指针the same寿命。编译器可以缩小重叠的生命周期,但在这种情况下这没有帮助。您已指定指向MyItr
s 与它们指向的事物具有相同的生命周期,and外部指针是可变的。
第二个问题是(即使在解决这个问题之后),您尝试做的事情是完全不安全的,并且会导致悬空指针。
这是一个more最小的例子:
struct S<'a> {
ptr: &'a i32,
}
fn f<'b>(t: &'b mut S<'b>, new_ptr: &'b i32) {}
fn main() {
let i0 = 1;
let mut s = S { ptr: &i0 };
let i1 = 2;
f(&mut s, &i1);
}
What is 'b
?嗯,编译器可以only生命周期很窄,所以通常你只会考虑你想要通过的所有事物的生命周期并选择最短的一个。在这种情况下,这将是i1
。所以,它必须缩短寿命&s
。指针的生命周期s
本身不是问题(你可以缩小借用的时间),但缩小内部生命周期(用于借用的生命周期)ptr
field) is一个问题。
如果编译器缩短了生命周期s.ptr
,然后你就可以存储&i1
在那个领域。s
期望s.ptr
超越自身,但这将不再是真的:i1
will 被摧毁 before s
是,意思是s.ptr
将包含一个悬空指针。和铁锈will not允许这种情况发生。
结果,铁锈can't narrow s
的内在'a
一生...但如果它不能缩小范围,那就意味着'b
必须是完整的、未缩小的'a
。但是等等,这意味着'b
比生命周期长s
itself and i1
。那是不可能的。
因此失败了。
该解决方案需要两件事。首先,您不需要过度指定生命周期。其次,您需要确保存在一些有效的生命周期at all;对于您的原始代码,这意味着移动i2
above z0
and z1
所以它比它们更长寿。就像这样:
fn f0<'a>(t0: &mut MyItr<'a>, t1: &mut MyItr<'a>, i: &'a i32) {
let t: &mut MyItr<'a> = std::cmp::max(t0, t1);
t.cur = i;
}
fn f1() {
let i0 = 1;
let i1 = 2;
let i2 = 3;
let mut z0 = MyItr { cur: &i0 };
let mut z1 = MyItr { cur: &i1 };
f0(&mut z0, &mut z1, &i2);
}
经验法则:不要到处乱发垃圾邮件。仅对应该相同的事物使用相同的生命周期。