LifeTimes in Rust
Hey Guys, This is my first article on RUST and in this, I will be talking about **lifetimes**.
TLDR, lifetime is something that denotes the lifetime of a value using a generic value.
according to the [documentation](https://doc.rust-lang.org/rust-by-example/scope/lifetime.html):- “A *lifetime* is a construct of the compiler (or more specifically, its *borrow checker*) which uses to ensure all borrows are valid. A variable’s lifetime begins when it is created and ends when it is destroyed in a scope”
The main aim of “lifetimes” in Rust is to prevent *dangling references*, “dangling references and wild references are **references/pointers that do not resolve to a valid destination**”
for eg
fn main() {
let x;
{ // a new scope starts
let y = 5;
x= &y; // passing a reference of 'x' to y;
}// scope ends
println!("x: {}", x);
}`
the output for the above code is
here as we can see that as the variable y will not be accessible as the inner scope ends. hence the inner scope is the lifetime of variable ‘y’.
The lifetime can be expressed in rust using 2 ways
- explicitly (annotation) :- lifetime can be annotated using generics, hence it can be used with “functions”, “Traits”, “Methods”, “Structs”, and “Bounds”
- implicitly (elision) :- lifetime can be simply elided as the lifetime which borrower-checked gets is a simple and a straight forward pattern.
Function:- In functions lifetimes can be annotated as well as elided, but there are some precautions to be followed when using lifetimes in the functions, otherwise can lead to failure of program at compile time.
“any reference being returned must have the same lifetime as an input or be static
.”
“a function can be given multiple lifetimes but using a single lifetime annotation increases readability ”
fn print_multi<'a, 'b>(x: &'a i32, y: &'b i32) {
println!("`print_multi`: x is {}, y is {}", x, y);
}
fn main() {
let x = 7;
let y = 9;
print_multi(&x, &y);
}
Lifetime works same with “Traits” “Methods” and “Structs”
on the other hand, “Bounds” are treated differently. to bound it we need to use “+” character
fn print_ref<'a, T>(t: &'a T) where
T: Debug + 'a {
println!("`print_ref`: t is {:?}", t);
}
There’s one special type of lifetime in rust, that is “static”, it is a lifetime that stays through-out the program. Generally to create a variable with static
lifetime is to create it with using static
keyword.
static NUM: i32 = 18;
let s: &'static str = "hello world";
Final Notes
Lifetime is a very subtle feature that allows us to understand the flow of a program and it is very different than scopes in Rust. In the next article i will be discussing about Scopes and we can compare how they’re different from lifetimes.
Also if you liked this article please show some love to it and follow me on LinkedIn, and Thank you for reading along.