Edward Alric
Edward Alric

Reputation: 61

How do lifetimes in Rust work for a function?

In the definition of lifetime_things, the lifetime of 'b is longer than 'a, but actually when I call this function, x1 is longer than y1, but this can compile successfully:

//here you could see 'b:'a means, the lifetime of b should be larger than a,
fn lifetime_things<'a,'b:'a>(x:&'a String, y:&'b String) ->&'a String {
  if x.len() > y.len() {
    &x
  } else {
    &y
  }
}

fn main() {
let z: i32;
    let x = String::from("1");
    let x1=&x;
    {
        let y = String::from("2");
        let y1=&y;
        println!("{}",lifetime_things(x1,y1));
    }
}

But here you could see the lifetime of x1 should be larger than y1 so why can this compile successfully as well?

Upvotes: 4

Views: 268

Answers (1)

Emoun
Emoun

Reputation: 2507

'b: 'a means 'b must outlive 'a, which in turn means whenever 'a is live, so must 'b. Crucially, this is a larger than or equals relationship. Also notice that lifetimes don't work like types. When a function takes an 'v reference, any lifetime ('w) will be accepted as long as 'w: 'v.

So, where is 'a live? In the body of the function and whenever the returned string reference is used after the call. We can visualize it like this:

fn lifetime_things<'a,'b:'a>(x:&'a String, y:&'b String) ->&'a String {
  if x.len() > y.len() {                         // <-+
    &x                                           //   |
  } else {                                       //   |
    &y                                           //   +----+
  }                                              //   |    |
}                                                // <-+    |
                                                 //        |
fn main() {                                      //        +-- 'a
let z: i32;                                      //        |
    let x = String::from("1");                   //        |
    let x1=&x;                                   //        |
    {                                            //        |
        let y = String::from("2");               //        |
        let y1=&y;                               //        |
        println!("{}",lifetime_things(x1,y1));   // <------+
    }
}

Notice, that since the value returned by lifetime_things is only printed, 'a is only live on the line println!("{}",lifetime_things(x1,y1)); (exclusing lifetime_thingss body).

So, to call lifetime_things we simply need the both arguments to at least be live at the call. This holds for both x1 and y1, so it all checks out.

Upvotes: 4

Related Questions