その変数が属してるスコープの事です。Rust では使用期限が過ぎた変数を使えない様に厳しく確認されます。
use std::borrow::Borrow;
fn plus<'a, 'b, T>(a: &'a T, b: &'b T) -> i32
where
T: Borrow,
{
a.borrow() + b.borrow()
}
fn main() {
{
// 'a
let thirty_three: i32 = 33;
{
// 'b
let one: i32 = 1;
assert_eq!(plus(&thirty_three, &one), 34);
}
}
}
main
処理の最初のブロックスコープには'a
、その中の2つ目のブロックスコープには'b
という名前が付いているとします。ここで変数thirty_three
のライフタイムは'a
、one
のライフタイムは'b
まはた'a
と考える事ができます。
Rust の関数ではジェネリック型を置く場所にライフタイムも置くことができます。関数plun
では'a
に属するT
の参照と、'b
に属するT
の参照を引数に期待するということになります。また上記の説明の通りライフタイムは'a
だけでも動きます。
fn plus<'a, T>(a: &'a T, b: &'a T) -> i32
where
T: Borrow,
{
a.borrow() + b.borrow()
}
実はライフタイムが1つしかなかったり、引数の値ぞれぞれが別のライフタイムを持つのでいい場合ライフライムは省略できます。
fn plus(a: &T, b: &T) -> i32
where
T: Borrow,
{
a.borrow() + b.borrow()
}
これはfn plus<'a, 'b, T>(a: &'a T, b: &'b T) -> i32
と展開されます。
先程'b
で定義した変数は'b
と'a
どちらにも属すると考えれると書きましたが、ライフタイムは'b
で定義した変数の参照を'a
なライフタイムの変数に入れることはできません。以下はエラーになります。
{
// 'a
let a = Foo { value: 33 };
let b;
{
// 'b
let c = Foo { value: 1 };
b = &c;
// error: `c` does not live long enough
}
}
これは'b
を抜けた後にb
が終わった変数c
の参照を持つことになってしまう為です。関数ではさらに子ブロックスコープに囲まれて生存期間がハッキリする為エラーにはなりません。