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 }
戻り値の参照が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 }
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 }
ライフタイム注釈は新しい制約を追加するのではなく、既にある関係をコンパイラに伝えるためのものです。
直し方: 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 }
'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 }
引数が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パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。