Lifetimes
https://doc.rust-lang.org/reference/lifetime-elision.html https://doc.rust-lang.org/reference/trait-bounds.html https://doc.rust-lang.org/reference/memory-allocation-and-lifetime.html
Now here comes of the more difficult things in Rust. All bindings in Rust have a "lifetime":
fn main() { // `x` doesn't exist yet { let x = 42; // `x` starts existing println!("x = {}", x); // `x` stops existing } // `x` no longer exists }
Similarly, references have a lifetime:
fn main() { // `x` doesn't exist yet { let x = 42; // `x` starts existing let x_ref = &x; // `x_ref` starts existing - it borrows `x` println!("x_ref = {}", x_ref); // `x_ref` stops existing // `x` stops existing } // `x` no longer exists }
The lifetime of a reference cannot exceed the lifetime of the variable binding it borrows:
fn main() { let x_ref = { let x = 42; &x }; println!("x_ref = {}", x_ref); // error: `x` does not live long enough }
A variable binding can be immutably borrowed multiple times:
fn main() { let x = 42; let x_ref1 = &x; let x_ref2 = &x; let x_ref3 = &x; println!("{} {} {}", x_ref1, x_ref2, x_ref3); }
While borrowed, a variable binding cannot be mutated:
fn main() { let mut x = 42; let x_ref = &x; x = 13; println!("x_ref = {}", x_ref); // error: cannot assign to `x` because it is borrowed }
While immutably borrowed, a variable cannot be mutably borrowed:
fn main() { let mut x = 42; let x_ref1 = &x; let x_ref2 = &mut x; // error: cannot borrow `x` as mutable because it is also borrowed as immutable println!("x_ref1 = {}", x_ref1); }
References in function arguments also have lifetimes. however, most of the time it is not specified (lifetime elision):
#![allow(unused)] fn main() { fn print(x: &i32) { // `x` is borrowed (from the outside) for the // entire time this function is called. } }
Functions with reference arguments can be called with borrows that have different lifetimes, so:
- All functions that take references are generic
- Lifetimes are generic parameters
- Lifetimes' names start with a single quote, ':
#![allow(unused)] fn main() { // elided (non-named) lifetimes: fn print(x: &i32) {} // named lifetimes: fn print<'a>(x: &'a i32) {} }
There is a special lifetime, named 'static, which is valid for the entire program's lifetime.
String literals are 'static:
struct Person { name: &'static str, } fn main() { let p = Person { name: "Satoshi Nakamoto", }; }