首页 > 解决方案 > Rust 生命周期的问题:impl 使用匿名生命周期,函数使用 <'a>,更改生命周期以匹配会导致错误

问题描述

您可以在此处运行代码片段。我删除了结构中的一堆不相关的函数和字段,以使事情更易于分析。

#[derive(Debug)]
pub struct Turtle<'a>{
    children: Vec<&'a Turtle<'a>>,
}

impl Turtle<'_>{
    pub fn new() -> Turtle<'static> {
        Turtle {children: Vec::new()}
    }
    pub fn add_child<'a>(&self, t: &'a Turtle<'a>) {
        &self.children.push(t);
    }
}

错误是

   |
11 |         &self.children.push(t);
   |                             ^ lifetime mismatch
   |
   = note: expected reference `&Turtle<'_>`
              found reference `&Turtle<'a>`
note: the lifetime `'a` as defined on the method body at 10:22...
  --> src/lib.rs:10:22
   |
10 |     pub fn add_child<'a>(&self, t: &'a Turtle<'a>) {
   |                      ^^
note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 6:13
  --> src/lib.rs:6:13
   |
6  | impl Turtle<'_>{
   |             ^^

问题似乎是因为 impl 有一个匿名生命周期,&self 有 Turtle<'_> 类型,所以 self.children 有匿名生命周期,这意味着 push 需要一个 Turtle<'_>。我想出了 2 个想法来解决这个问题,即将 impl 更改为 <'a> 或将参数 t 的生命周期更改为 <'_>,但都没有奏效。我了解如何确保单个函数的生命周期是正确的,但是当涉及到所有连接在一起的各种函数、结构和实现时,事情开始变得不清楚。

标签: rustlifetime

解决方案


您的结构需要一个生命周期,您选择将其称为“a”。然后,那个生命被“给予”或“与”self.children 共享。稍后,您为匿名生命周期实现您的结构,这是结构定义声明 self.children 也必须共享的生命周期。但是,您的“新”功能意味着创建具有“静态”生命周期的 self.children(并且 'static != '_ 因为 '_ 可能比 'static 更短)。此外,您的 add child 方法需要一个(可能)完全独立的生命周期,您也将其称为“a”(只是因为您将其称为“a”并不会使其与您在结构定义中命名的“a”相同)。尝试创建一个采用类型而不是生命周期的新结构(例如 T 或 V)?如果两者都没有界限,那么它们将基本上相等。这同样适用于生命周期。

实际的解决方案在于匹配您的生命周期。由于结构的自引用性质,您不能使用匿名生命周期,因为编译器需要知道在添加子节点时生命周期匹配。现在编译下面的内容。注意使用 Self 来推断创建时的生命周期 <'a>。您也可以使用 Turtle<'a> 但我个人会考虑更轻松地使用 Self,因为它避免了额外的生命周期引用。此外,为了使您的 add_child 方法起作用,对“self”的引用需要是可变的(请参阅 &mut self)。这是因为您正在修改 self.children 的内容并因此改变结构。

请注意,这将适用于“任何”生命周期,无论您将其称为 'a 或 'z 还是其他任何名称。关键是编译器可以推断出所涉及的所有内容的生命周期都是匹配的。

    #[derive(Debug)]
    pub struct Turtle<'a> {
        children: Vec<&'a Turtle<'a>>,
    }

    impl<'a> Turtle<'a> {
        pub fn new() -> Self {
            Self { children: Vec::new() }
        }

        pub fn add_child(&mut self, t: &'a Turtle<'a>) {
            self.children.push(t);
        }
    }

推荐阅读