1

I have been learning the lifetimes topic for the last three days, and they start making sense to me now. However, I experimented a lot, but didn't manage to specify lifetimes in a way when they'd lead to runtime-unsafe behavior, because the compiler seems to be smart enough to prevent such cases, by not compiling. Hence I have the chain of questions below:

Is it true that Rust compiler will catch every case of unsafe lifetime specifiers usage?

  • If yes, then why does Rust require manually specifying lifetimes, when it can do it on its own, by deducing the unsafe scenarios? Or is it just a relic that will go away once the compiler becomes powerful enough to make lifetime elision everywhere?
  • If no, what is the example (are the examples) of unsafe lifetime specifiers usage? They'd clearly prove the necessity of manually specifying lifetimes.
Nurbol Alpysbayev
  • 19,522
  • 3
  • 54
  • 89

1 Answers1

3

It is not possible (barring any compiler bugs) to induce undefined behavior with lifetime specifiers unless you use unsafe code (either in the function or elsewhere). However, lifetime specifiers are still necessary because sometimes there is ambiguity in what the proper lifetime should be. For example:

fn foo(bar: &i32, baz: &i32) -> &i32 {
    // ...
}

What should the lifetime of the return type be? The compiler cannot infer this because it could be tied to either bar or baz, and each case would affect how long the return value lasts and therefore how the function can be used. The body of the function cannot be used to infer the lifetime because type and lifetime checks must be possible to complete using only the signature of the function. The only way to remove this ambiguity is to explicitly state what lifetime the return value should have:

fn foo<'a>(bar: &i32, baz: &'a i32) -> &'a i32 {
    // ...
}

You can read more about the lifetime elision rules here.

pengowen123
  • 1,007
  • 1
  • 12
  • 23