当第二个参数用 'a 注释时,第一个参数的隐式生命周期是多少?

What is the implicit lifetime for the 1st argument when the 2nd argument is annotated with 'a?

在阅读 Rust Book Chapter 12.4 时,我偶然发现了这个函数:

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    vec![]
}

我理解为什么代码在没有 contents 参数和 return 值的显式生命周期注释的情况下无法编译 - lifetime elision rules 不适用于至少两个借用的论点。

但我很好奇 query 参数的隐式生命周期注释是什么。我可以想到两种情况:

// Scenario 1
pub fn search<'a>(query: &'a str, contents: &'a str) -> Vec<&'a str> {
    vec![]
}
// Scenario 2
pub fn search<'a, 'b>(query: &'b str, contents: &'a str) -> Vec<&'a str> {
    vec![]
}

两种方案都编译,因此 query 获得生命周期 'a'b。哪一个是正确的?

来自 rustonomicon,在 lifetime elision 下:

Each elided lifetime in input position becomes a distinct lifetime parameter.


您可以尝试将函数分配给错误的类型。编译器会告诉你函数的正确类型:

let x: () = search;

Playground

结果:

error[E0308]: mismatched types
 --> src/main.rs:6:17
  |
6 |     let x: () = search;
  |            --   ^^^^^^ expected `()`, found fn item
  |            |
  |            expected due to this
  |
  = note: expected unit type `()`
               found fn item `for<'r, 'a> fn(&'r str, &'a str) -> Vec<&'a str> {search}`

所以,你的函数类型是:

for<'r, 'a> fn(&'r str, &'a str) -> Vec<&'a str> {search}

此外,如果 query 也有生命周期 'a,你应该可以这样做:

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    vec![query]
}

但是编译失败,因为 query 的生命周期不是 'a

Playground

一种思考方式是,我们不是 'giving' 带有生命周期注释的生命周期,而是描述 return 值的生命周期如何与输入的生命周期相关。

生命周期已经存在,但是注释让我们可以设置它们之间的关系。由于您永远不会将 query 的生命周期与情况 2 中的任何其他内容相关联,因此我们真的不需要命名它。直观地说,这是最常见的情况,如果您没有对 query.

进行注释,编译器应该(确实)推断出这种情况