Lifetimes in Rust, Why and How

Lifetimes in Rust, Why and How

What is lifetime

Lifetimes tells how long references would be valid, ensuring memory safety without a garbage collector.

Does not compile

fn longest (x:& str, y:& str) -> & str{
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
fn main() {
    let string1 = String::from("Hi");
    {
        let string2 = String::from("Hello");
        let result = longest (string1.as_str(), string2.as_str());
        println! ("{result}");
    }
}

$ cargo build
3 | fn longest(x:& str, y:& str) -> & str{
    |              -----    -----     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but 
    the signature does not say whether it is borrowed from `x` or `y`
  help: consider introducing a named lifetime parameter        

Why compliation error? Compiler is unable to infer the lifetimes of parameters

Compiles (With Lifetime Annotation)

Lifetime? Prefix every parameter with ‘k. Apostrophe (‘k), denotes reference has generic lifetime.

fn longest <'k> (x:&'k str, y:&'k str) -> &'k str{
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
fn main() {
    let string1 = String::from("Hi");
    {
        let string2 = String::from("Hello ");
        let result = longest (string1.as_str(), string2.as_str());
        println! ("{result}");
    }
}

$ cargo run
Hello        

How this worked? Rust can’t tell whether the reference being returned refers to x or y Borrow checker can’t determine lifetime of return value will relate to x or y. With changed function signature, We tell compiler, returned reference will be valid as long as both the parameters are valid.

Lifetime in struct

Why we need lifetime in struct?

if we want to store reference in struct, ie struct does not hold Owned types.

Will not compile

struct A {
    x:&str
}
fn main() {
    let m = String::from("test");
    let o = A {
        x : &m,
    };
    println!("{}", o.x);
}
$ cargo run
missing lifetime specifier
--> src/main.rs:6:7
6 |     x:&str
  |       ^ expected named lifetime parameter        

Compiles (With Lifetime)

struct A <'a> {
    x : &'a str,
}
fn main() {
    let m = String::from("test");
    let o = A {
        x : &m,
    };
    println!("{}", o.x);
}
$ cargo run
test        

Lifetime Ellision

The patterns programmed into Rust complier which applies lifetime rules in desired situtation automatically. These are not rules for programmers to follow; they’re a set of particular cases that the compiler will consider, and if your code fits these cases, you don’t need to write the lifetimes explicitly. Input Lifetime: Lifetimes on function or method parameters Output lifetimes: lifetimes on return values

3 rules to figure out the lifetimes

Rule-1(applies to input lifetimes)

compiler assigns a lifetime parameter to each parameter that’s a reference. 1 parameter gets one lifetime parameter, 2 parameters gets 3 separate lifetime parameters & so on

                fn foo (x: &i32); becomes
                fn foo <'a>(x: &'a i32);

                fn foo (x:&i32, y:&i32) becomes
                fn foo <'a, 'b>(x: &'a i32, y: &'b i32)        

Rule-2(applies to input lifetimes)

if there is exactly one input lifetime parameter, that lifetime is assigned to all output lifetime parameters.

fn foo <'a>(x: &'a i32) -> &'a i32        

Rule-3

if there are multiple input lifetime parameters, but one of them is &self or &mut self, lifetime of self is assigned to all output lifetime parameters.

To view or add a comment, sign in

More articles by Amit K.

  • Stored Procedures, Functions in Postgresql

    Stored Procedure Stored Procedure User defined functions stored in database which contains set of SQL statements It can…

  • Troubleshooting Nvidia GPU for ML Workload

    Scenario You are a owner/admin of GPU Farm. These GPUs are placed on standalone docker containers.

  • Getting started with OpenGL

    What is OpenGL This is a library for 2D and 3D graphics rendering. It provides API(Application Programming Interface)…

  • Pyunit or Unitest

    Used to test a unit of source code Features: 1. PyUnit is very simple yet very flexible 2.

  • Calling OpenAI APIs from code

    Steps a. Get openAI API Key openaAI API Key b.

    3 Comments
  • FlatList with Example in React Native

    What is FlatList? displays a scrolling list of changing, but similarly structured, data. Unlike the more generic…

  • Create Postgres Database, Tables, Schema using Diesel(ORM) Rust

    What is Diesel Diesel is a ORM(object-relational mapping). ORM is programming technique that connects object-oriented…

  • Location Sharing App System Design (Bump)

    What is Bump Bump is location sharing Mobile App. Install bump on 2 phones(add as friends).

  • Load Balancers & Caches

    What is Load Balancer? Load Balancer evenly distributes incoming traffic/load among webservers/workers that are defined…

  • REST API / Representation State Transfer

    Restful Web Server/Application? Web application that implements HTTP CRUD methods in Restful way. Eg: Twitter, facebook…

Insights from the community

Others also viewed

Explore topics