Kiwi breeder
Kiwi breeder

Reputation: 617

Clarification on Rust lifetime syntax

The canonical example I see when dealing with Rust lifetimes is the following func:

pub fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
   if x.len() > y.len() {
      x
   } else {
      y
   }
}

Interestingly, this seems to translate to "the lifetime of the result of longest() is the shortest lifetime of it's input parameters". The logic makes sense to me but I don't understand how this is communicated by the syntax.

When I look at the function it looks like there is one lifetime 'a and the function seems to be enforcing that x and y must have the exact same lifetime 'a and so the result must have the same lifetime 'a.

I'm not sure if this syntax is essentially syntax sugar for what I'm seeing. If I was allowed to be verbose, then I think the syntax would look something like (it's not correct syntax, I know):

pub fn longest<'a, 'b>(x: &'a str, y: &'b str) -> min('a, 'b) str {
   if x.len() > y.len() {
      x
   } else {
      y
   }
}

Am I understanding this correctly or am I mis-interpreting the language?

Upvotes: 4

Views: 435

Answers (2)

George
George

Reputation: 2801

As I read it, in the following:

pub fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
   if x.len() > y.len() {
      x
   } else {
      y
   }
}

the statement fn longest<'a>(x: &'a str, y: &'a str) -> &'a str

  1. introduces the single lifetime label, 'a, into the scope of the function
  2. labels the shortest remaining lifetime of the two unnamed string slices targeted by the reference arguments, x and y, with the lifetime label, 'a. Now 'a has a constraint.
  3. returns a reference to an unnamed string slice that is guaranteed to live as long as, 'a. The compiler will now ensure that the caller does not presume the result will live longer than the shortest lifetime of the arguments it provides.

Note:

  • The lifetime label is associated with the target of the reference and not the reference itself. That is references are read as, & (description of the thing referenced such as its lifetime, type, etc.).
  • References are basic things useful for accessing their targets and only valid while their targets are alive. Consequently, it is inherently presume that that the lifetime of the reference will never exceed the lifetime of the target and so need not be specified (unless it becomes a target of a reference itself).
  • Lifetime is determined by program flow. labelling merely surfaces what is already there to allow the expression of relationships (requirements and guarantees). In other languages such constraints would be invisible and unchecked by the compiler. Granted, the compiler can reject valid programs though it will never accept an invalid one.

Upvotes: 0

Sven Marnach
Sven Marnach

Reputation: 601609

A lifetime parameter of 'a means that the reference needs to live for at least the lifetime 'a. It's fine to pass in a reference that lasts longer than 'a.

When the function longest() is called, the compiler needs to infer the lifetime 'a from the concrete parameters that are passed in. The compiler is smart enough to infer this lifetime as the intersection of the actual lifetimes of x and y, making sure each parameter satisfies the lifetime bounds.

In essence, this means your interpretation is right.

Upvotes: 4

Related Questions