Paul Razvan Berg
Paul Razvan Berg

Reputation: 21460

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

While reading Chapter 12.4 of the Rust Book, I stumbled upon this function:

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

I understand why the code doesn't compile without the explicit lifetime annotation for the contents argument and the return value - the lifetime elision rules do not apply for functions with at least two borrowed arguments.

But I'm curious what's the implicit lifetime annotation for the query argument. I could think of two scenarios:

// 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![]
}

Both scenarios compile, so query gets either lifetime 'a or 'b. Which one is correct?

Upvotes: 9

Views: 394

Answers (2)

matt_t_gregg
matt_t_gregg

Reputation: 192

One way to think of it is that we're not 'giving' a lifetime with lifetime annotations, but describing how the lifetime of your return value relates to the lifetimes of your inputs.

Lifetimes already exist, but annotations let us set relations between them. As you never relate the lifetime of query to anything else in situation 2, we shouldn't really need to name it. Intuitively this makes sense as the most common case and the one that the compiler should (does) infer if you make no annotation on query.

Upvotes: 3

Mihir Luthra
Mihir Luthra

Reputation: 6779

From the rustonomicon, under lifetime elision:

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


You can try assigning the function to a wrong type. Compiler will tell you the correct type of the function:

let x: () = search;

Playground

Result:

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}`

So, type of your function is:

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

Also, if query also had lifetime 'a, you should be able to do this:

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

But this fails to compile because query's lifetime is not 'a.

Playground

Upvotes: 9

Related Questions