为包括内部引用在内的方法推断适当的生命周期

Infer an appropriate lifetime for methods including interior references

我正在学习 Rust 并面临编译问题。我简化了我的代码(所以它现在没有任何意义)post 我的问题在这里。

我有一个 Parent 结构,其中填充了一个 ChildWrapper 和一个 Vec<&Child>。但是编译器不会让我设置引用,因为创建的引用不一定比它的内容长。在我看来,在这里设置生命周期 (pub fn get<'a>(&'a self) -> &'a Child {) 应该可以让编译器放心,ref 会存在足够长的时间……但是,不。

如果我从 Parent 中取出 ChildWrapper 我可以让它工作,但我仍然不明白我的代码有什么问题。

struct Child {
    e: bool,
}

impl Child {
    pub fn new() -> Child {
        Child { e: true }
    }
}

struct ChildWrapper {
    child: Child,
}

impl ChildWrapper {
    pub fn new() -> ChildWrapper {
        ChildWrapper { child: Child::new() }
    }

    pub fn get<'a>(&'a self) -> &'a Child {
        &self.child
    }
}

struct Parent<'a> {
    child_ref: Vec<&'a Child>,
    wrapper: ChildWrapper,
}

impl<'a> Parent<'a> {
    pub fn new() -> Parent<'a> {
        Parent {
            child_ref : Vec::new(),
            wrapper: ChildWrapper::new(),
        }
    }

    pub fn set_child_ref(&mut self) {
        self.child_ref.push(self.wrapper.get());
    }
}

fn main() {
    let mut parent = Parent::new();
    parent.set_child_ref();
}

这是我遇到的错误:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:41:36
   |
41 |         self.child_ref.push(self.wrapper.get());
   |                                          ^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 40:2...
  --> src/main.rs:40:2
   |
40 |       pub fn set_child_ref(&mut self) {
   |  _____^
41 | |         self.child_ref.push(self.wrapper.get());
42 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:41:23
   |
41 |         self.child_ref.push(self.wrapper.get());
   |                             ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 32:6...
  --> src/main.rs:32:6
   |
32 | impl<'a> Parent<'a> {
   |      ^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:41:23
   |
41 |         self.child_ref.push(self.wrapper.get());
   |                             ^^^^^^^^^^^^^^^^^^

我知道如何解决这个问题,这可能是设计不好的迹象(或者可能不是?),但我正在寻找一个解释,并最终寻找一个使用相同架构的解决方案... 比如如何为 self.wrapper.get() 明确设置正确的生命周期?

谢谢!

To my eyes setting lifetimes here (pub fn get<'a>(&'a self) -> &'a Child {) should reassure the compiler the ref will live long enough... but, nah.

您在此处提供的生命周期注解与您省略它们时 Rust 编译器会推断出的完全相同,因此这不会产生任何影响。

正如所写,您的 set_child_ref 方法省略了生命周期,这意味着推断的生命周期如下:

impl<'a> Parent<'a> {
    pub fn set_child_ref<'b>(&'b mut self) {
        self.child_ref.push(self.wrapper.get());
    }
}

这行不通。生命周期 'b 将取决于 set_child_refcaller 如何使用参数。因此,对 self 的引用可能比生命周期 'a 更短。这会导致问题,因为您存储在 child_ref 中的对 ChildWrapper 的引用是从该(可能寿命较短的)引用中借用的。

简单的解决方法是,对 self 的引用必须比 'a 长,这是 child_ref 向量中引用的生命周期:

impl<'a> Parent<'a> {
    pub fn set_child_ref(&'a mut self) {
        self.child_ref.push(self.wrapper.get());
    }
}