是的,这个错误可能令人困惑,但它是有正当理由的。
struct SubImage<'a> {
image: &'a mut Image<'a>,
offset: (i32, i32),
size: (i32, i32),
}
在这里你声明引用Image
必须活下去完全一样长作为图像本身内部借用的数据 - 相同的生命周期参数'a
既用于参考又用作参数Image
: &'a mut Image<'a>
.
然而,render2()
违反此要求。实际签名为render2()
如下:
fn render2<'b, 'a>(image: &'b mut Image<'a>)
因此,它试图创造SubImage
with &'b mut Image<'a>
, where 'b
不一定等于'a
(在这种特殊情况下,它肯定不会),因此编译器会退出。
此外,这样的签名是您可以在提供该函数时调用该函数的唯一原因&mut image
in main()
, 因为&mut image
有生命周期image
变量,但是Image
该变量包含的生命周期为pixel_data
稍长一些。以下代码不是有效的 Rust,但它接近编译器理解事物的方式,并且它演示了问题:
fn main() {
'a: {
let mut pixel_data: Vec<u8> = Vec::new();
'b: {
let mut image: Image<'a> = Image::new(&'a mut pixel_data, (1280, 720));
render2::<'b, 'a>(&'b mut image);
}
}
}
当你声明render2()
as
fn render2<'a>(image: &'a mut Image<'a>)
你确实将问题“推”到了上游 - 现在该函数根本无法被调用&mut image
,你现在可以明白为什么了——它需要统一'a
and 'b
一生,这是不可能的,因为'a
长于'b
.
正确的解决方案是使用单独的生命周期来参考Image
and Image
本身在SubImage
定义:
struct SubImage<'b, 'a:'b> {
image: &'b mut Image<'a>,
offset: (i32, i32),
size: (i32, i32),
}
Now 'b
and 'a
可能有不同的生命周期,但为了使其发挥作用,你必须绑定'a
一生与'b
, 那是,'a
必须至少活到'b
。这正是您的代码所需的语义。如果不强制执行此约束,则引用的图像可能会在引用超出范围之前“死亡”,这违反了 Rust 的安全规则。