首页 > 解决方案 > 如何使用 structs 和 impl 的生命周期来推断实现的适当生命周期?

问题描述

如何解决此错误?当我在中使用“匿名生命周期”时,我到底在告诉编译器什么impl

struct LineHandlerInfo<'a> {
    label: &'a str,
    match_literal: &'a str,
    f: fn(&str) -> Option<&str>,
}

struct Game<'a> {
    handlers: Vec<LineHandlerInfo<'a>>,
}

impl Game<'_> {
    fn match_str<'a>(
        &'a mut self,
        label: &'a str,
        match_literal: &'a str,
        mut f: fn(&str) -> Option<&str>,
    ) {
        let mut lh = LineHandlerInfo {
            label,
            match_literal,
            f,
        };
        self.handlers.push(lh);
    }
}

fn main() {
    let mut g = Game {
        handlers: Vec::new(),
    };
    g.match_str("echo hello", "hello", |s| {
        println!("{}", s);
        None
    });
}

当我尝试编译时,出现以下错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:18:22
   |
18 |         let mut lh = LineHandlerInfo {
   |                      ^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 12:18...
  --> src/main.rs:12:18
   |
12 |     fn match_str<'a>(
   |                  ^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:19:13
   |
19 |             label,
   |             ^^^^^
note: but, the lifetime must be valid for the lifetime '_ as defined on the impl at 11:11...
  --> src/main.rs:11:11
   |
11 | impl Game<'_> {
   |           ^^
   = note: ...so that the expression is assignable:
           expected LineHandlerInfo<'_>
              found LineHandlerInfo<'_>

我该如何解决这个错误,impl Game当我在结构上已经有生命周期时指定生命周期时,我到底告诉编译器什么?

标签: rustlifetime

解决方案


我该如何解决这个错误,当我在 impl Game 上指定一个生命周期时,当我在结构上已经有一个生命周期时,我到底告诉编译器什么?

我怀疑您的困惑源于对 Rust 中声明和使用生命周期的方式的不完全理解。

结构生命周期

为了在结构上使用生命周期,您在要声明的结构名称附近声明生命周期<>,然后在结构定义中引用该生命周期。重要的是,请注意,在那里声明的生命周期仅限于结构定义 - 它在外部没有任何意义。

例如(使用@Shepmaster 提供的 MRE):

struct Game<'a> {
    handlers: Vec<&'a str>,
}

该结构Game包含一个对字符串的引用向量,并且被引用的字符串必须至少与该Game结构一样长。

实现生命周期

当在 impl 块上使用生命周期说明符时,您在 impl 关键字的相邻项内声明生命周期<>,之后您可以在正在实现的结构和实现本身中引用生命周期,如下所示:

impl<'b> Game<'b> {
    fn match_str(&mut self, label: &'b str) {
        self.handlers.push(label);
    }
}

请注意,我在这里使用了一个完全不同的生命周期名称 ( 'b) 来说明结构上的生命周期声明独立于 impl 块上的声明。

打破这个:

impl<'b>

这意味着我们正在为结构定义一个实现,并且在该定义中我们将使用生命周期'b

 Game<'b> {

这意味着 impl 适用于Game具有生命周期的结构'b- 因此在此实现内部的任何引用self也将自动具有生命周期'b

fn match_str(&mut self, label: &'b str) {

在这里,我们定义了match_str接受参数的方法labellabel是一个字符串切片,它也具有生命周期'b- 因此它必须至少持续与self调用该方法的时间一样长。

在您的原始代码中,您有以下内容:

impl Game<'_> {
    fn match_str<'a>(&mut self, label: &'a str) {
    ...
    }
}

这告诉编译器:

  • 您正在启动一个新的 impl 块,并且没有在 impl 级别声明的生命周期
  • 该实现是针对 struct 的Game;这个结构有一个生命周期参数,但我们不关心它,我们不会将它绑定到实现的任何元素
  • 我们正在定义一个方法match_str,并且我们正在声明一个生命周期'a,我们可以在函数签名的其余部分中引用它
  • 我们有一个label具有生命周期的论点a,但我们没有将这一生命周期与其他任何事物联系起来

更多信息:


推荐阅读