Code Fix

中級

E0106: missing lifetime specifier の原因と直し方

参照を返す関数で、その参照が複数の引数のどちらに由来するのかコンパイラが判断できない場合、E0106エラーになります。ライフタイム注釈を付けて、戻り値の参照がどの引数と同じ生存期間なのかを明示する必要があります。

エラーメッセージの読み方

error[E0106]: missing lifetime specifier
E0106
エラーコード — `rustc --explain E0106` で詳しい説明が見られます
missing lifetime specifier
詳細メッセージ — 何が問題だったか

このエラーが出る典型パターン

パターン1

 1  fn longer(a: &str, b: &str) -> &str {             
                             ^
 2      if a.len() > b.len() { a } else { b }
 3  }
 4  
 5  fn main() {
 6      println!("{}", longer("hi", "hello"));
 7  }
error[E0106]: missing lifetime specifier

戻り値の参照がaとbのどちらに由来するのかコンパイラは判断できません。同じライフタイム'aで結びつける必要があります。

直し方: fn longer(a: &str, b: &str) -> &str {fn longer<'a>(a: &'a str, b: &'a str) -> &'a str { にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  fn shorter(x: &str, y: &str) -> &str {             
                             ^
 2      if x.len() < y.len() { x } else { y }
 3  }
 4  
 5  fn main() {
 6      println!("{}", shorter("abc", "de"));
 7  }
error[E0106]: missing lifetime specifier

2つの参照引数から1つを選んで返す関数は、ライフタイム注釈が無いと戻り値の由来が曖昧になります。

直し方: fn shorter(x: &str, y: &str) -> &str {fn shorter<'a>(x: &'a str, y: &'a str) -> &'a str { にします。

この問題を解いてみる →

パターン3

 1  fn pick(first: &str, second: &str) -> &str {             
                                ^
 2      if first.len() >= second.len() { first } else { second }
 3  }
 4  
 5  fn main() {
 6      println!("{}", pick("aa", "b"));
 7  }
error[E0106]: missing lifetime specifier

ライフタイム注釈は新しい制約を追加するのではなく、既にある関係をコンパイラに伝えるためのものです。

直し方: fn pick(first: &str, second: &str) -> &str {fn pick<'a>(first: &'a str, second: &'a str) -> &'a str { にします。

この問題を解いてみる →

パターン4

 1  fn choose(left: &str, right: &str) -> &str {             
                                ^
 2      if left.len() == right.len() { left } else { right }
 3  }
 4  
 5  fn main() {
 6      println!("{}", choose("xy", "zz"));
 7  }
error[E0106]: missing lifetime specifier

'aという名前自体に特別な意味はなく、同じ記号を使うことで生存期間が同じであることを示しています。

直し方: fn choose(left: &str, right: &str) -> &str {fn choose<'a>(left: &'a str, right: &'a str) -> &'a str { にします。

この問題を解いてみる →

パターン5

 1  fn max_str(p: &str, q: &str) -> &str {             
                             ^
 2      if p.len() > q.len() { p } else { q }
 3  }
 4  
 5  fn main() {
 6      println!("{}", max_str("a", "bb"));
 7  }
error[E0106]: missing lifetime specifier

引数が1つだけなら省略規則で自動的に決まりますが、2つ以上の参照から選ぶ場合は明示が必要です。

直し方: fn max_str(p: &str, q: &str) -> &str {fn max_str<'a>(p: &'a str, q: &'a str) -> &'a str { にします。

この問題を解いてみる →

よくある誤解

「関数の中で辻褄が合っていれば、参照の生存期間はコンパイラが自動的に推論してくれるはず」という思い込みは誤りです。複数の引数から参照を返す可能性がある場合、コンパイラは自力で判断できず、明示的なライフタイム注釈を要求します。

まとめ

E0106: missing lifetime specifierは中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)