为什么生命周期省略对于返回 Fn 的函数不起作用?

Kod*_*dra 2 closures lifetime rust

根据The Rust Book 的说法,终身省略允许我们拥有这个签名:

fn first_word(s: &str) -> &str {
...
}
Run Code Online (Sandbox Code Playgroud)

而不是这个更详细的版本:

fn first_word<'a>(s: &'a str) -> &'a str {
...
}
Run Code Online (Sandbox Code Playgroud)

后来在同一本书中,我发现我不能这样写:

fn make_a_cloner(s: &str) -> impl Fn() -> String {
  move || s.to_string()
}
Run Code Online (Sandbox Code Playgroud)

我必须给返回类型一个生命周期:

fn make_a_cloner(s: &str) -> impl Fn() -> String + '_ {
...
}
Run Code Online (Sandbox Code Playgroud)

我有点困惑。为什么我们在返回 a 时不需要指定任何生命周期,但在返回 a 时&str需要添加生命周期?为什么相同的省略规则不适用于这两种情况?'_impl Fn() -> String

kmd*_*eko 6

尽管生命周期省略可能会让人感到困惑,但 Rust 的语法确实希望在发生借用时能够保持清晰。引用就是这样一个地方,它是一个明确的借用者,甚至对于具有生命周期的结构,我们也鼓励您将其用于MyStruct<'_>参数和参数,以便生命周期是显而易见的。编译器中有一个elided_lifetimes_in_pathslint 可以帮助解决这个问题,但不幸的是默认情况下是允许的;我鼓励您将其添加到您自己的代码中。

但是,当您返回 a impl Trait(没有生命周期)时,就没有注释来表明已发生借用。添加占位符生命周期+ '_至少可以向编译器和其他开发人员传达正在发生借用的信息。因此,如果没有生命周期注释返回 aimpl Trait'static默认使用,除非特征类型的其他部分传递借用(即将由,而不是impl Trait<&'a T>绑定)。'a'static

这不一定适用于impl Trait其他地方(例如函数参数)。