Return 包含在需要生命周期参数的结构中的引用

Return reference wrapped in struct that requires lifetime parameters

如何 return 包装在结构中的引用以及需要什么样的生命周期注解?我很难提出我的确切问题,但以下示例说明了我正在尝试做的事情。我有一个结构 C,其中包含对需要生命周期参数的结构 B 的引用。我想要 C 上的一个函数,它 return 是对 B 的引用,包裹在另一个用作接口的结构 Borrower 中。

编译时 returning Borrower: 'cannot infer an appropriate lifetime for lifetime parameter 'b due to conflicting requirements' 时出现错误。我该如何解决这个问题?我可以输入哪些生命周期参数?我觉得 'a'b 都不是正确的生命周期。

Playground

struct C<'a, 'b> {
    ref2: &'a mut B<'b>,
}

impl<'a, 'b> C<'a, 'b> {
    fn get_borrower(&mut self) -> Borrower {
        Borrower { ref3: self.ref2 }
    }
}

struct Borrower<'a, 'b> {
    ref3: &'a mut B<'b>,
}

impl<'a, 'b> Borrower<'a, 'b> {
    fn print_and_add(&mut self) {
        println!("ref is {}", self.ref3.ref1.i);
        self.ref3.ref1.i += 1;
    }
}

struct B<'a> {
    ref1: &'a mut A,
}

struct A {
    i: u32,
}

fn main() {
    let mut a = A { i: 10 };
    let mut b = B { ref1: &mut a };
    let mut c = C { ref2: &mut b };

    for _ in 0..10 {
        let mut borrower = c.get_borrower();
        borrower.print_and_add();
    }
}

问题具体出在这个方法上:

impl<'a, 'b> C<'a, 'b> {
    fn get_borrower(&mut self) -> Borrower {
        Borrower { ref3: self.ref2 }
    }
}

我们需要帮助编译器理解返回的 Borrower 中需要哪些生命周期参数,因为这里推断的生命周期是不正确的:生命周期省略 Borrower 可以扩展为 Borrower<'_, '_> 其中匿名生命周期都是 &mut self 的生命周期;如果我们称它为 's,则等效签名为:

    fn get_borrower<'s>(&'s mut self) -> Borrower<'s, 's> {

这显然是不对的,因为我们知道第二个生命期应该是'b,正如B<'b>类型的字段ref2直接描述的那样。使用以下签名(并修复不相关的错误后),the code compiles successfully:

    fn get_borrower(&mut self) -> Borrower<'_, 'b> {

有趣的部分在第一个参数中。人们可能倾向于假设我们希望它是 'a 而不是 's,但这仍然会导致生命周期冲突:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
 --> src/main.rs:7:9
  |
7 |         Borrower { ref3: self.ref2 }
  |         ^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime `'s` as defined on the method body at 6:21...
 --> src/main.rs:6:21
  |
6 |     fn get_borrower<'s>(&'s mut self) -> Borrower<'a, 'b> {
  |                     ^^
note: ...so that reference does not outlive borrowed content
 --> src/main.rs:7:26
  |
7 |         Borrower { ref3: self.ref2 }
  |                          ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
 --> src/main.rs:5:6
  |
5 | impl<'a, 'b> C<'a, 'b> {
  |      ^^
note: ...so that the expression is assignable
 --> src/main.rs:7:9
  |
7 |         Borrower { ref3: self.ref2 }
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: expected `Borrower<'a, 'b>`
             found `Borrower<'_, '_>`

这是因为我们在对 self 的 mutable 引用后面检索 ref2,并且它有自己的生命周期。我们不能强行将它移出 self 来实现生命周期 'a,也不能传递一个 &'s mut &'a mut B<'b>。因此,返回 Borrower<'s, 'b> 是正确的做法:因为隐含 'a: 's'a's 长),此生命周期中的协方差将使该方法能够将可变引用 &'a mut B<'b> 缩小到其子类型 &'s mut B<'b>.

 ---------- 
| 'a       |
| ------   |
|| 's   | ---> Borrower<'s, 'b>
||      |  |
| ------   |
 ----------

另请参阅:

  • mutably borrow fields from a mutably borrowed struct