コンテンツにスキップ

Rustのコンパイルエラー解説

Rust のコンパイラから赤いエラーが出て、何を言われているのかよくわからない……そんなときは、このページから始めましょう。こうしたエラーは、Rust を書く人なら誰でも、ときには1日に何度も目にするものです。うれしいことに、何度も出会うエラーはほんのいくつかしかありません。一度わかってしまえば、もう怖くありません。

下の各ページでは、エラーコードを1つずつ取り上げて、実際のメッセージを見せ、その意味をやさしい言葉で説明し、ブラウザで実行できる直し方を紹介します。

エラー コンパイラのメッセージ ひとことで言うと
E0382 borrow of moved value 値を渡してしまったあとで、もう一度使おうとした
E0502 cannot borrow as mutable because it is also borrowed as immutable 誰かがまだ読んでいる最中に、その値を書き換えようとした
E0499 cannot borrow as mutable more than once at a time 2か所が同時に同じ値を書き換えようとした
E0308 mismatched types 期待されている型とは違う型を渡した
E0277 the trait bound is not satisfied その型には、頼んだこと(表示・比較・足し算など)ができない
E0106 missing lifetime specifier 返した参照がいつまで有効なのか、Rust にはわからない
E0425 cannot find value in this scope 名前のつづりが違うか、その名前が使えるブロックの外で使っている
E0599 no method named … found その型にはそのメソッドがないか、トレイトを use していない
E0384 cannot assign twice to immutable variable mut を付けていない変数を書き換えた
E0596 cannot borrow as mutable, as it is not declared as mutable mut でない変数や参照を通して、値を書き換えようとした
E0597 borrowed value does not live long enough 指している値がなくなったあとも、参照を使おうとしている
E0515 cannot return reference to local variable 関数の終わりで破棄される値への参照を返した
E0373 closure may outlive the current function, but it borrows … クロージャ(よくあるのはスレッド)が、先になくなるかもしれないローカル変数を借用している
E0369 binary operation == cannot be applied to type … 自分の型が ==、<、+ などに(まだ)対応していない
E0432 unresolved import use の行が、見つからないクレート・モジュール・アイテムを指している
E0433 cannot find type … in this scope (older: failed to resolve) HashMap::new() のようなパスに、インポートしていない(または存在しない)名前が使われている
E0424 self value is a keyword only available in methods with a self parameter self を受け取らない関数の中で self を使った
E0061 this function takes N arguments but M arguments were supplied 引数が多すぎるか少なすぎる(Rust には省略可能な引数がない)
E0594 cannot assign to p.hp, as p is not declared as mutable mut でのアクセスなしに、フィールドや & の先の値を書き換えた
E0004 non-exhaustive patterns: X not covered match がありうる値をすべて扱っていない
E0507 cannot move out of x which is behind a shared reference 借りているだけのものの所有権を取ろうとした
E0603 function x is private pub でない関数・構造体・モジュールを使った
E0716 temporary value dropped while borrowed 行の終わりで捨てられる値への参照を持ち続けた
E0463 can’t find crate for x クレート(またはターゲット用の標準ライブラリ)がインストールされていない
E0368 binary assignment operation += cannot be applied to type … 自分の型が +=、-= などに対応していない
E0057 this function takes N arguments but M were supplied (note: closure defined here) クロージャを呼ぶときの引数が多すぎるか少なすぎる
E0282 type annotations needed Rust が自分で型を決められないので、型を書いてあげる必要がある
E0609 no field x on type T フィールド名のつづりが違うか、値が(Option などに)包まれている
E0593 closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments タプル(または別の数の引数)が期待されているのに、クロージャが別々の引数を受け取っている
E0631 type mismatch in closure arguments クロージャの引数の型が、渡される値と合わない(i32 と &i32 の違いが多い)
E0005 refutable pattern in local binding let Some(x) = … は失敗することがあるので、ふつうの let では受け付けてもらえない
E0615 attempted to take value of method len on type String s.len() ではなく s.len と書いた
E0610 {integer} is a primitive type and therefore doesn’t have fields 数値・bool・char に .field を付けた
E0560 struct User has no field named nmae 構造体を作るときに、その構造体にないフィールド名を書いた
E0616 field balance of struct Account is private pub でないフィールドを、モジュールの外から読んだ
E0451 field x of struct Y is private 非公開のフィールドがある構造体を、構造体リテラルで作ろうとした
E0624 method x is private pub でないメソッドや関連関数を呼んだ
E0283 type annotations needed (cannot infer type … multiple impls satisfy this bound) 当てはまる型がいくつもある(.collect()、.sum() など)ので、1つ選ぶ必要がある
E0284 type annotations needed: cannot satisfy <_ as FromStr>::Err == _ "42".parse() が、どの型にパースすればいいのかわからない
E0790 cannot call associated function on trait without specifying the corresponding impl type どの型なのかを書かずに Default::default() や Trait::new() を呼んだ
E0559 variant Shape::Circle has no field named r 列挙型のバリアントを作るときに、そのバリアントにないフィールド名を書いた
E0063 missing field email in initializer of User 構造体を作るときに、フィールドを1つ以上書き忘れた
E0689 can’t call method pow on ambiguous numeric type {integer} 2.pow(10) や 2.0.sqrt() には、i32 や f64 のような具体的な数値の型が必要
E0034 multiple applicable items in scope 2つのトレイトが同じ名前のメソッドを型に与えていて、Rust がどちらか選べない
E0412 cannot find type X in this scope (Rust 1.93+ prints E0425) 型の名前のつづりが違うか、インポートや宣言をしていない
E0428 the name area is defined multiple times 2つのアイテムが同じ名前を使っている(Rust には関数のオーバーロードがない)
E0026 variant Shape::Circle does not have a field named r パターンに、構造体やバリアントにないフィールドの名前を書いている
E0027 pattern does not mention fields id, paid 構造体のパターンにフィールドが足りない。追加するか、最後に .. を書く
E0533 expected unit struct, unit variant or constant, found struct variant Shape::Circle ただの名前が来るべき場所で、構造体バリアント(や関数)を使っている。{ .. } を付ける
E0592 duplicate definitions with name reset 2つの impl ブロックで、同じ名前のメソッドを定義している
E0255 the name Error is defined multiple times use でインポートした名前が、自分の型や関数と同じ
E0252 the name Result is defined multiple times 2つの use の行が同じ名前を持ち込んでいる。片方を as で名前を変える
E0411 cannot find type Self in this scope impl やトレイトの外で Self を使った
E0405 cannot find trait Display in this scope トレイトの名前のつづりが違うか、インポートしていない(例:use std::fmt::Display;)
E0532 expected unit struct, unit variant or constant, found tuple variant Shape::Circle パターンでタプルバリアント(や構造体)の ( ) を書き忘れたか、いらない ( ) を付けている
E0164 expected tuple struct or tuple variant, found struct variant Shape::Circle パターンで、構造体バリアントや関連アイテムに ( ) を付けている。{ } かマッチガードを使う
E0404 expected trait, found derive macro Debug impl X for や T: X の X が、構造体や型エイリアス、インポートしていない derive マクロになっている
E0401 can’t use generic parameters from outer item 内側の fn が外側の関数の T や Self を使っている。自分のジェネリクスを付けるか、クロージャを使う
E0107 enum takes 2 generic arguments but 1 generic argument was supplied Result<u32> や HashMap<String> など、< > の中の型が足りないか多すぎる
E0530 match bindings cannot shadow tuple variants (use Shape::* のあとの)Circle => のような、( ) のないバリアント名は新しい変数にできない
E0434 can’t capture dynamic environment in a fn item 内側の fn からは外側のローカル変数が見えない。クロージャを使うか、引数で渡す
E0601 main function not found in crate main バイナリに fn main() がない(書き忘れ、つづりの間違い、mod の中にある、本当はライブラリ)
E0658 use of unstable library feature iter_intersperse stable の Rust で nightly 専用の API を使った。stable の代わりの方法を使うか、Rust を更新する
E0614 type u32 cannot be dereferenced x が参照ではなくただの値なのに、*x と書いた
E0435 attempt to use a non-constant value in a constant const、配列の長さ、static に let の変数を使った。const にするか、Vec を使う
E0554 #![feature] may not be used on the stable release channel nightly 専用のコードをコピーした。属性を消して stable の API を使うか、わかったうえで nightly を使う

表の真ん中の列は、ターミナルに表示されるとおり英語のままにしています。rustc のエラーメッセージは、どの国でも英語で表示されるからです。

Rust のエラーメッセージはとても親切なことで有名ですが、情報がぎっしり詰まっています。実際の例を見てみましょう。

fn main() {
let name = String::from("Ferris");
let greeting = name;
println!("{name}");
}
error[E0382]: borrow of moved value: `name`
--> src/main.rs:4:16
|
2 | let name = String::from("Ferris");
| ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait
3 | let greeting = name;
| ---- value moved here
4 | println!("{name}");
| ^^^^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let greeting = name.clone();
| ++++++++

次の順番で読んでいきます。

  1. 最初の行は要約です。エラーコード(E0382)と、1行の説明が書かれています。
  2. 矢印の行(--> src/main.rs:4:16)は、問題が起きたファイル・行・列を教えてくれます。
  3. ^^^^ の印は、エラーが起きたちょうどその場所を指しています。---- の印は、そこに至るまでの経緯です。この例では「値は2行目で作られ、3行目でムーブされ、4行目で使われた」と言っています。
  4. help: は、コンパイラがおすすめする直し方です。追加すべきコードがそのまま書かれていることもよくあります(++++ の印が新しく足す文字です)。いつも最善の直し方とは限りませんが、出発点としてはとても役に立ちます。

読み始めるのは最初のエラーからです。1つの間違いが、あとに続くエラーを次々と引き起こすことがあります。最初の1つを直すだけで、残りが消えてしまうこともよくあります。

  • コンパイラにもっと詳しく聞く。 どのエラーコードにも、長めの説明が組み込まれています。ターミナルで次のように実行してみましょう。

    Terminal window
    rustc --explain E0382

    短い説明と、エラーになる例、直した例が表示されます(説明は英語です)。

  • こまめにチェックする。 cargo check はプログラム全体をビルドせずにエラーを見つけるので、cargo build よりずっと速く終わります。数行書くたびに実行すれば、エラーに出会うのは一度に1つずつで済み、20個まとめて、ということにはなりません。詳しくはCargoとクレートを見てください。

  • 書いている最中にエディタでエラーを表示する。 rust-analyzer 拡張機能を使うと、同じ help のテキスト付きで、エラーがコードの中に直接表示されます。詳しくはRustのツールと環境構築を見てください。

ここに並んでいるエラーのほとんどは、ほかの言語なら実行時になって(あるいは永遠に)気づかないことを、Rust がプログラムを実行する前にチェックしているから存在します。解放済みのメモリを使う、2つのスレッドが同じデータを書き換える、null のチェックを忘れる、といったことです。エラーを1つ直すたびに、ユーザーのもとに届くはずだったバグが1つ消えています。

だから「Rust ではコンパイル時に戦って、そのあとはプログラムがそのまま動く」とよく言われます。よく出るエラーの背景にあるルールは、所有権、借用、ライフタイムで解説しています。

理解度チェック

1. Rust のエラーにいくつか問題が表示されました。最初に直すべきなのはどれですか?

2. rustc --explain E0382 は何をしますか?

3. エラーメッセージの中で、^^^^ の印は何を示していますか?

スコア: 0 / 3