It is recommended to increase the default lifetimes

So, if I understand your proposal, you're asking to add a lifetime elision rule such that:

  • it doesn't apply in the existing cases
  • it applies when there's at least one argument whose type is the same as the output one
  • and sets the lifetime of the output to be the same as the lifetime of those arguments

While this may work in simple cases, can you show it applies in more complex ones as well? Even if it does make the current function compile, can you show it is the most correct solution in most cases? The danger is that this would make those functions compile for beginners, then they would be confused because their use doesn't work, and since the function compiled fine it should be correct, right?

For example, let's take this function:

fn test(x: &str, y: &str) -> &str {
    "test"
}

The "most correct" lifetime annotation is:

fn test(x: &str, y: &str) -> &'static str {
    "test"
}

But with your proposal it would by default be:

fn test<'a>(x: &'a str, y: &'a str) -> &'a str {
    "test"
}

Now, if someone tries to use it like this:

fn example_use1() -> &'static str {
    let s1 = String::from("1");
    let s2 = String::from("2");
    test(&s1, &s2)
}

Then this would work with the "most correct" lifetime, but would fail with yours. Similarly when the function returns only one of the parameter (and always that one!) then adding the same lifetime to the other parameter make the lifetime of the returned value overconstrained.

Overall I feel like it's bad to introduce lifetime elision rules for beginners. They are useful for very common cases because they help experienced programmers avoid putting lifetimes annotations everywhere, but beginners should be incentivized to use them to understand what they do, and only after learn lifetime elision rules that allow them to skip lifetime annotations.

4 Likes