The problem
Dangling reference is bad, we don’t want it.
How rust compiler helps
Rust compiler use borrow checker to validate references, every reference has a lifetime.
fn main {
let x: i32 = 0; //------------------+--- 'b
// |
let y: &i32 = &x; //----+--'a |
// | |
println!("x: {}", y); //----+-------------+
}
- Every reference must be valid, no dangling reference is possible.
- Immutable reference must not be changed anywhere in it’s lifetime.
a: T = ...;
x: &T = &a;
y: &mut T = &mut a;
// x's life time stops here, or x can't be used after y is declared.
// becase after y is declared, we can't promise `a` is unchanged.
println!("{}", x); // compiler error
Explicitly annotating lifetime
Most of the time, lifetime are implicit and inferred. But there are cases when lifetime can be ambigous, such as:
fn foo(x: &str, y: &str) -> &str {
// ...
}
the return value’s lifetime could be equal to x
or y
, which is unknown for the compiler. So we need annotate it explicity:
// in english: return value will be validate, as long as both x and y are valid
fn foo<'a>(x: &'a str, y: &'a str) -> &'a str {
}
// 'a could be 'foo 'bar 'shit...,
// but we use 'a 'b 'c ... in convention
then the return values’s lifetime is min(x's lifetime, y's lifetime)
Lifetime Elision
Rust compiler use three rules
- every reference is assigned a lifetime
- if there are only 1 input reference, then it’s lifetime is assigned to every output reference
- if there are
&self
or&mut self
, then it’s lifetime is …
After using these 3 rules, if there’re still output reference’s lifetime is unclear, then compiler will report an error
Static lifetime
let s: &'static str = "fuck";
s is embedded in the program’s binary, (rodata?)