Lifetimes ensure that the scope of a reference doesn't outlive the scope of the resource it is referring to.
#[derive(Debug)]
struct Foo {
f : i32
}
fn main() {
let x: &Foo;
let a = Foo { f : 0 };
x = &a; // error: `a` does not live long enough
println!("x: {:?}", x);
}
{ x a x=&a }
reference x <------------------->
lifetime #1 <*************>
borrow error
#[derive(Debug)]
struct Foo {
f :i32
}
fn main() {
let a = Foo { f : 0 };
let x: &Foo;
x = &a;
println!("x: {:?}", x); // x: Foo { f: 0 }
}
{ a x x=&a }
lifetime #1 <********************>
reference x <-------------->
borrow ok
Returned lifetime = union of the scopes of all references linked to the returned address.
#[derive(Debug)]
struct Foo {
f : i32
}
#[allow(unused_variables)]
fn f2<'b>(r2: &'b Foo, r3: &'b Foo) -> &'b Foo {
r2
}
fn f1<'a>(r1: &'a Foo) -> &'a Foo {
let s2 = Foo { f : 22 };
let r4 = f2(&r1, &s2);
r4
}
fn main() {
let s1 = Foo { f : 11 };
let r5 = f1(&s1);
println!("r5: {:?}", r5);
}
{ s1 { r1 s2 { r2 r3 } r4 } r5 }
resource s1 <****************************>
reference r1 <------------------>
reference r4 <-->
reference r5 <-->
lifetime ‘a <=======================>
reference r2 <----->
reference r4 <-->
reference r5 <-->
lifetime ‘b <===============>
resource s2 <***************>
error: s2 does not live during the whole lifetime ‘b
#[derive(Debug)]
struct Foo {
f : i32
}
#[allow(unused_variables)]
fn f2<'b, 'c>(r2: &'b Foo, r3: &'c Foo) -> &'b Foo {
r2
}
fn f1<'a>(r1: &'a Foo) -> &'a Foo {
let s2 = Foo { f : 22 };
let r4 = f2(&r1, &s2);
r4
}
fn main() {
let s1 = Foo { f : 11 };
let r5 = f1(&s1);
println!("r5: {:?}", r5);
}
{ s1 { r1 s2 { r2 r3 } r4 } r5 }
resource s1 <****************************>
reference r1 <------------------>
reference r4 <-->
reference r5 <-->
lifetime ‘a <=======================>
reference r2 <----->
reference r4 <-->
reference r5 <-->
lifetime ‘b <===============>
resource s2 <***************>
reference r3 <-->
lifetime ‘c <==>
Struct field lifetime = union of the scopes of all references linked to the address stored in that field.
#[derive(Debug)]
struct Foo {
f : i32
}
#[derive(Debug)]
struct Bar<'b> {
r4 : &'b Foo,
r5 : &'b Foo
}
#[allow(unused_variables)]
fn f2<'b>(r2: &'b Foo, r3: &'b Foo) -> Bar<'b> {
Bar { r4 : r2, r5 : r3 }
}
fn f1<'a>(r1: &'a Foo) -> &'a Foo {
let s2 = Foo { f : 22 };
let r6 = f2(&r1, &s2).r4;
r6
}
fn main() {
let s1 = Foo { f : 11 };
let r7 = f1(&s1);
println!("r7: {:?}", r7);
}
{ s1 { r1 s2 { r2 r3 { r4 r5 } } r4 r5 r6 } r7 }
s1 <********************************************>
r1 <---------------------------------->
r4 <-------->
r6 <-->
r7 <-->
‘a <=======================================>
r2 <--------------->
r4 <----->
r4 <-------->
r6 <-->
r7 <-->
‘b <===============================>
s2 <*******************************>
error: s2 does not live during the whole lifetime ‘b
#[derive(Debug)]
struct Foo {
f : i32
}
#[derive(Debug)]
struct Bar<'b, 'c> {
r4 : &'b Foo,
r5 : &'c Foo
}
#[allow(unused_variables)]
fn f2<'b, 'c>(r2: &'b Foo, r3: &'c Foo) -> Bar<'b, 'c> {
Bar { r4 : r2, r5 : r3 }
}
fn f1<'a>(r1: &'a Foo) -> &'a Foo {
let s2 = Foo { f : 22 };
let r6 = f2(&r1, &s2).r4;
r6
}
fn main() {
let s1 = Foo { f : 11 };
let r7 = f1(&s1);
println!("r7: {:?}", r7);
}
{ s1 { r1 s2 { r2 r3 { r4 r5 } } r4 r5 r6 } r7 }
s1 <********************************************>
r1 <---------------------------------->
r4 <-------->
r6 <-->
r7 <-->
‘a <=======================================>
r2 <--------------->
r4 <----->
r4 <-------->
r6 <-->
r7 <-->
‘b <===============================>
s2 <*******************************>
r3 <---------->
r5 <-->
r5 <----->
‘c <=======================>