生存期間の代数(ライフタイム注釈)
from 項目14:生存期間を理解しよう
コードでは 生存期間 に任意の名前を付けることができる(ライフタイム注釈)
e.g. 'a, 'b, 'c
コンパイラは、この名前がコードの中のどの スコープ を指しているのかを内部的に解釈して、生存期間を管理する
開発者はこの情報を直接見ることはできない
ライフタイム注釈を用いると、出力の参照値の生存期間がどの入力の参照値のスコープに依存するのか を明示することができる
warning.icon 'static は例外('static ライフタイム)
e.g. 引数に 1 つの参照値を受け取り、1 つの参照値を返す関数
('static 以外で)唯一使えるのは入力の生存期間だけなので、以下のようになる
code:rs
pub fn first<'a>(data: &'a Item) -> Option<&'a Item> {
// ...
}
ただし、上記のケースは一般的であり、生存期間省略ルール に当てはまるため明示する必要はない
code:rs
pub fn first(data: Item) -> Option<Item> {
e.g. 引数に 2 つの参照値を受け取り、1 つの参照値を返す関数
一意に決まらないため、ライフタイム注釈が必須
pub fn find<'a>(haystack: &'a [u8], needle: &'a [u8]) -> Option<&'a [u8]>
pub fn find<'a, 'b>(haystack: &'a [u8], needle: &'b [u8]) -> Option<&'a [u8]>
したがって、以下のコードはコンパイルエラーとなる
code:rs
pub fn find(haystack: &u8, needle: &u8) -> Option<&u8> {
// ...
}
warning.icon ライフタイム注釈が同じであっても、生存期間が同じということはではない
ライフタイム注釈の目的は、アイテムへの参照がアイテム自身よりも長く存在しないことを保証すること である
これを踏まえると、入力と出力に同じライフタイム注釈を付与している場合、出力は入力よりも長く生存できない ことを表している
また、引数の 2 つの値に同じライフタイム注釈を付与している場合、出力は生存期間が短い方の入力よりも長く生存できない ことを表している
code:rs
{
let outer = Item { contents: 7 };
{
let inner = Item { contents: 8 };
{
let min = smaller(&inner, &outer);
} // min がドロップされる
} // inner がドロップされる
} // outer がドロップされる
一方、どちらか一方の引数のみを参照している場合、戻り値のライフタイムがもう一方の生存期間を包含する必要はない
pub fn find<'a, 'b>(haystack: &'a [u8], needle: &'b [u8]) -> Option<&'a [u8]> {
code:rs
{
let heystack = b"123456789"; // 生存期間 'a の開始点
let found = {
let needle = b"234"; // 生存期間 'b の開始点
find(heystack, needle);
}; // 生存期間 'b の終了点
} // 生存期間 'a の終了点
#Rust #Effective_Rust_―_Rustコードを改善し、エコシステムを最大限に活用するための35項目