ruk·si

🦀 Rust
Lifetime

Updated at 2024-01-04 06:26

Lifetimes ensure that references to values do not live longer than the values themselves.

fn main() {
    let hello;
    {                           // a new scope is introduced
      let greeting = "hello";   // the string value is owned by `greeting`
      hello = &greeting;        // `hello` borrows the value from `greeting`
    }
    println!("{}", hello);      // no using the borrowed value outside scope
    // error[E0597]: `greeting` does not live long enough
}

Lifetime names start with a single quote '. Every reference has a lifetime parameter, but they are frequently implicit. But sometimes compiler will need additional guidance to deduce programmer's intent. This allows returning references whose lifetime depends on the lifetime of the arguments.

// elided lifetime:
fn print(x: &i32) {}

// expanded lifetime:
fn print<'a>(x: &'a i32) {}

When there is a single input lifetime, it doesn't need to be named.

fn number_value<'a>(num: &'a Number) -> &'a i32 {
    &num.value
}

// ==

fn number_value(num: &Number) -> &i32 {
    &num.value
}

There is a special lifetime, 'static, which means "the entire program's runtime".

struct Person {
    name: &'static str,
}

fn main() {
    let p = Person {
        name: "Ruksi",
    };
}

Lifetime nesting with generics is sometimes useful:

// "any references in T live at least as long as T"
struct Ref<'a, T: 'a>(&'a T);

Sources