I'm still not sure if I understand lifetime annotations.
The common example is a simple function like
fn max(a: &i32, b: &i32) -> &i32 {
if a < b { *c } else { a }
}
If I try to compile that without lifetime annotations, I get an "expected lifetime parameter" error for the return value.
The usual explanation is that the compiler can't know if the return value points to the memory from a
or from b
.
But if I change this to:
fn max<'a, 'b>(a: &'a i32, b: &'b i32) -> &'a i32 {
if a < b { b } else { a }
}
I get:
10 | fn max<'a, 'b>(a: &'a i32, b: &'b i32) -> &'a i32 {
| ------- -------
| |
| this parameter and the return type are declared with different lifetimes...
11 | if a < b { b } else { a }
| ^ ...but data from `b` is returned here
So obviously the compiler knows where the return value can come from, so it should be able to assign them appropriate lifetime annotations automatically.
Of course if this wouldn't be an implementation but just a trait definition, then that wouldn't work.
So do we have lifetime annotations just for traits or are there actual cases where the compiler couldn't figure them out automatically?