TL;DR

決まった形の関数シグネチャでは、Rust のライフタイム注釈を省略できる、というルールである。省略した注釈は、コンパイラが一定の規則で補う。

仕組み

関数のライフタイム注釈は、次のどれかに当てはまる場合に省略できる。

  1. 1 つの引数が参照を受け取り、1 つ以上の参照を返す場合は、戻り値は引数と同じライフタイムを持つとみなされる
  2. 1 つ以上の引数が参照を受け取り、参照を返さない場合は、各引数がそれぞれ別のライフタイムを持つとみなされる
  3. &self を含む 1 つ以上の引数が参照を受け取り、1 つ以上の参照を返す場合は、戻り値は &self と同じライフタイムを持つとみなされる

推論できないライフタイムを省略するとコンパイルエラーになる。

例

それぞれのルールで、左の省略形は右の明示形と等しい。

// 1. 戻り値は引数と同じライフタイム
pub fn f(x: &Item) -> (&Item, &Item)
pub fn f<'a>(x: &'a Item) -> (&'a Item, &'a Item)
 
// 2. 引数ごとに別のライフタイム
fn f(x: &Item, y: &Item, z: &Item) -> i32
fn f<'a, 'b, 'c>(x: &'a Item, y: &'b Item, z: &'c Item) -> i32
 
// 3. 戻り値は &self と同じライフタイム
fn f(&self, y: &Item, z: &Item) -> &Thing
fn f<'a, 'b, 'c>(&'a self, y: &'b Item, z: &'c Item) -> &'a Thing

注意点

省略された生存期間が求めるものと違う場合は、ライフタイム注釈を明示的に書いて指定する。ただし、実際には最初から注釈を書くことはほとんどない。呼び出し側での参照の使い方と合わないというエラーメッセージが出てから、書き直すことが大半である。

関連

出典