できない.dev

Rust で「missing lifetime specifier」が解消できない

参照を返す関数や参照を持つ構造体で E0106 が出るのは、コンパイラがその参照をどの入力から借りたのか決められないためである。
ライフタイム引数を明示するか、借用をやめて所有権のある型を返すかで解決する。

公開: 更新:

実行例あり(2026-10-01 に実環境で検証)

要約

error[E0106]: missing lifetime specifier は「参照を書いたが、その参照がどれだけ生きるのかコンパイラに伝わっていない」という意味である。
借用チェックに失敗しているのではなく、シグネチャに情報が足りないだけなので、ライフタイム引数を書けば通る。

fn longest(x: &str, y: &str) -> &str {
    if x.len() > y.len() { x } else { y }
}
error[E0106]: missing lifetime specifier
 --> src/main.rs:1:33
  |
1 | fn longest(x: &str, y: &str) -> &str {
  |               ----     ----     ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the
          signature does not say whether it is borrowed from `x` or `y`

戻り値が x と y のどちらから借りたのかは、本文を読まないと分からない。
Rust は本文を見ずにシグネチャだけで判断する設計なので、ここで止まる。

実行例

rustc 1.98.1 では、引数が 2 つある関数の戻り値、参照を持つ構造体のフィールド、所有値しか受け取らない関数の戻り値の 3 か所で E0106 が出て、impl Parser のライフタイム省略は E0726 になった。
コンパイラの help が示すとおり 'a や '_ を付けるか、戻り値を String にすると、どれも cargo run が通る。

$ rustc --version
rustc 1.98.1 (48a229cea 2026-09-01)
$ cargo build -q
error[E0106]: missing lifetime specifier
 --> src/main.rs:1:33
  |
1 | fn longest(x: &str, y: &str) -> &str {
  |               ----     ----     ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
help: consider introducing a named lifetime parameter
  |
1 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
  |           ++++     ++          ++          ++
 
For more information about this error, try `rustc --explain E0106`.
error: could not compile `demo` (bin "demo") due to 1 previous error
$ echo $?
101
$ cargo run -q
dekinai
$ echo $?
0
$ cargo build -q
error[E0106]: missing lifetime specifier
 --> src/main.rs:2:12
  |
2 |     input: &str,
  |            ^ expected named lifetime parameter
  |
help: consider introducing a named lifetime parameter
  |
1 ~ struct Parser<'a> {
2 ~     input: &'a str,
  |
 
For more information about this error, try `rustc --explain E0106`.
error: could not compile `demo` (bin "demo") due to 1 previous error
$ echo $?
101
$ cargo build -q
error[E0726]: implicit elided lifetime not allowed here
 --> src/main.rs:5:6
  |
5 | impl Parser {
  |      ^^^^^^ expected lifetime parameter
  |
help: indicate the anonymous lifetime
  |
5 | impl Parser<'_> {
  |            ++++
 
For more information about this error, try `rustc --explain E0726`.
error: could not compile `demo` (bin "demo") due to 1 previous error
$ echo $?
101
$ cargo run -q
a,b
$ echo $?
0
$ cargo build -q
error[E0106]: missing lifetime specifier
 --> src/main.rs:1:28
  |
1 | fn banner(name: String) -> &str {
  |                            ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
  |
1 | fn banner(name: String) -> &'static str {
  |                             +++++++
help: instead, you are more likely to want to change the argument to be borrowed...
  |
1 | fn banner(name: &String) -> &str {
  |                 +
help: ...or alternatively, you might want to return an owned value
  |
1 - fn banner(name: String) -> &str {
1 + fn banner(name: String) -> String {
  |
 
For more information about this error, try `rustc --explain E0106`.
error: could not compile `demo` (bin "demo") due to 1 previous error
$ echo $?
101
$ cargo run -q
== dekinai ==
$ echo $?
0

— 2026-10-01 時点の出力

検証環境

検証日
実行環境
rust:1 Debian GNU/Linux 13 (trixie)
バージョン
  • Python 3.13.5
  • Git 2.47.3

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. 入力の参照が 2 つ以上ある: Lifetime elision(新しいタブで開く) の省略規則で戻り値のライフタイムが自動的に決まるのは、入力の参照が 1 つのときか、メソッドで &self があるときだけである。
    それ以外は明示が必要になる。
  2. 構造体が参照を持っている: struct Parser { input: &str } のように書くと、その構造体が借用元より長生きしないことを保証できないため同じエラーになる。
  3. 借用元が存在しない: fn make() -> &str のように入力に参照が無い場合、返せる参照は 'static なものしか無い。
    関数内で作った値を返したいなら参照では表現できない。
  4. impl 側の書き忘れ: 型にライフタイム引数を足しても、impl Parser のままだと今度は impl 側でエラーになる。
    こちらは E0106 ではなく error[E0726]: implicit elided lifetime not allowed here で、コンパイラは impl Parser<'_> と書くよう提案する(rustc 1.98.1 で確認)。

解決策

1. 借用元と戻り値を同じライフタイムで結ぶ

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

'a は「x と y の短いほうが生きている間」を表す。
呼び出し側はその範囲でだけ戻り値を使える。

2. 片方だけから借りるなら片方だけに付ける

戻り値が常に第 1 引数から借りるのであれば、第 2 引数にライフタイムは要らない。

fn prefix<'a>(text: &'a str, sep: &str) -> &'a str {
    text.split(sep).next().unwrap_or(text)
}

必要以上に引数を同じ 'a で縛ると、呼び出し側の自由度が下がる。

3. 構造体と impl の両方に宣言する

struct Parser<'a> {
    input: &'a str,
}
 
impl<'a> Parser<'a> {
    fn new(input: &'a str) -> Self {
        Parser { input }
    }
 
    fn rest(&self) -> &str {
        self.input
    }
}

rest のようにメソッドで &self がある場合は省略規則が働くので、戻り値のライフタイムは書かなくてよい。

4. 借用をやめる

関数内で組み立てた文字列を返したいときは、参照ではなく所有権のある型にする。

fn banner(name: &str) -> String {
    format!("== {name} ==")
}

'static を付ければコンパイルが通る場合もあるが、それはリテラルなど本当にプログラム終了まで生きる値に限られる。
迷ったら String を返すほうが安全である。

この記事は役立ちましたか?