在使用生命周期参数调用函数时,如何处理struct参数的生命周期?

dac*_*ker 5 rust

此代码通过编译器(为了澄清生命周期,不会被省略):

struct Foo<'a> {
    _field: &'a i32,
}

fn test<'a, 'b, 'c>(_x: &'a mut Foo<'c>, _y: &'b bool) {  // case 1
}

fn main() {
    let f = &mut Foo { _field: &0 };
    {
        let p = false;
        test(f, &p);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用'b的,而不是'ctest像这样的定义:

fn test<'a, 'b>(_x: &'a mut Foo<'b>, _y: &'b bool) {  // case 2
}
Run Code Online (Sandbox Code Playgroud)

代码无法编译("p不能长寿")!

test在案例2 的调用中我期望发生的事情是:

  • 'a设置为实际生命周期f,
  • 'b被设置为相交Foo的实际寿命和&p的实际寿命是&p的寿命,

一切都应该没问题,如案例1所示.

相反,在案例2中实际上似乎发生的事情'b是被迫成为生命周期Foo过长&p的生命周期,因此编译器错误"p不能长寿".真正?

甚至更陌生(案例3):如果test采用&mut,这只会失败.如果我离开<'b>,但删除之mut类似:

fn test<'a, 'b>(_x: &'a Foo<'b>, _y: &'b bool) {  // case 3
}
Run Code Online (Sandbox Code Playgroud)

代码再次传递.

谁有人对此有所了解?

干杯.

She*_*ter 4

注意到与的差异mut是一个关键的观察结果。我认为如果您更改第二个参数的类型并给出一种可能的实现,则会更有意义:

fn test<'a, 'b>(_x: &'a mut Foo<'b>, _y: &'b i32) {
    _x._field = _y;
}
Run Code Online (Sandbox Code Playgroud)

这个函数有变异的能力_x。该突变还包括将新引用存储_field. 然而,如果我们能够存储一个生命周期较短的引用(你提到的交集),那么一旦内部块结束, 中的引用Foo就会变得无效,我们就会违反 Rust 的内存安全保证!

当您使用不可变引用时,就不会出现这种危险,因此编译器允许这样做。

你发现了一件重要的事情 - Rust 并不总是关心你在函数中做了什么。检查函数调用是否有效时,仅使用函数的类型签名。

我确信有一种奇特的方式可以使用诸如逆变协方差之类的正确术语来表达这一点,但我对这些术语的了解还不足以正确使用它们!^_^

  • 在情况 1 中,由于 &amp;mut,'c 获得 Foo 的原始生命周期。'b 是独立的,不会造成伤害。在情况 2 中,同样由于 &amp;mut,'b 获得 Foo 的原始生命周期。这次, &amp;p “太短”,无法放入 &amp;'b 布尔值中,因此“p 的寿命不够长”。在情况 3 中,允许将 'b 缩短为 &amp;p 的生命周期,因为不存在将 _field 测试更改为比原始 Foo “短”的引用的危险。希望,我理解正确。 (2认同)