エラーメッセージの読み方
Rustコンパイラのエラーメッセージを正しく読み解く方法を学びます。
エラーメッセージの構造
error[E0382]: borrow of moved value: `s`
--> src/main.rs:4:20
|
2 | let s = String::from("hello");
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait
3 | let s2 = s;
| - value moved here
4 | println!("{}", s);
| ^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let s2 = s.clone();
| ++++++++
各部分の説明
-
エラーコード:
error[E0382]E0382は一意のエラーコードrustc --explain E0382で詳細な説明が見られる
-
エラーの要約:
borrow of moved value: 's'- 何が問題かの簡潔な説明
-
ファイル位置:
--> src/main.rs:4:20- ファイル名:行番号:列番号
-
コードスニペット: エラー箇所のコードと注釈
|の後にコードが表示される^や-でエラー箇所を指示- 追加の説明が付く
-
help: 修正方法の提案
- 具体的なコード修正が提案される
エラーレベル
error(エラー)
error[E0382]: ...
- コンパイルが失敗する
- 必ず修正が必要
warning(警告)
warning: unused variable: `x`
- コンパイルは成功する
- 潜在的な問題を示唆
- 修正することを推奨
note(注記)
note: required by a bound in `HashMap::insert`
- 追加の情報を提供
- エラーの原因を理解するのに役立つ
help(ヘルプ)
help: consider borrowing here: `&x`
- 具体的な修正案
- 積極的に参考にしよう
読み方のコツ
1. エラーコードを確認する
# 詳細な説明を見る
rustc --explain E0382
これにより、エラーの詳細な説明と例が表示されます。
2. 最初のエラーから修正する
error[E0382]: ...
error[E0599]: ...
error[E0308]: ...
複数のエラーがある場合、最初のエラーを修正すると他のエラーも消えることが多い。
3. 注釈を丁寧に読む
2 | let s = String::from("hello");
| - move occurs because `s` has type `String`
↑ この説明が重要
- や ^ の横の説明文が問題の原因を教えてくれます。
4. helpを活用する
help: consider cloning the value
|
3 | let s2 = s.clone();
| ++++++++
+ で囲まれた部分が追加すべきコードです。
実践例
例1: 型の不一致
error[E0308]: mismatched types
--> src/main.rs:2:18
|
2 | let x: i32 = "hello";
| --- ^^^^^^^ expected `i32`, found `&str`
| |
| expected due to this
読み方:
mismatched types: 型が一致しないexpected i32, found &str:i32を期待したが&strがあったexpected due to this: 型注釈i32が原因
修正:
#![allow(unused)]
fn main() {
let x: i32 = 42; // i32にする
// または
let x: &str = "hello"; // &strにする
}
例2: 借用ルール違反
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> src/main.rs:4:5
|
3 | let first = &v[0];
| - immutable borrow occurs here
4 | v.push(4);
| ^^^^^^^^^ mutable borrow occurs here
5 | println!("{}", first);
| ----- immutable borrow later used here
読み方:
cannot borrow as mutable: 可変借用できないimmutable borrow occurs here: 行3で不変借用mutable borrow occurs here: 行4で可変借用しようとしたimmutable borrow later used here: 行5で不変借用がまだ使われている
修正: 不変借用を先に使い切る
#![allow(unused)]
fn main() {
let mut v = vec![1, 2, 3];
let first = &v[0];
println!("{}", first); // 先に使う
v.push(4); // その後で変更
}
例3: ライフタイム不足
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 {
| ++++ ++ ++ ++
読み方:
missing lifetime specifier: ライフタイム指定子がないhelp: 戻り値が借用値だが、xとyのどちらか不明consider introducing...: 具体的な修正案
修正: helpの提案通りに
#![allow(unused)]
fn main() {
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
}
例4: トレイト未実装
error[E0277]: `MyStruct` doesn't implement `Debug`
--> src/main.rs:8:22
|
8 | println!("{:?}", my_struct);
| ^^^^^^^^^ `MyStruct` cannot be formatted using `{:?}`
|
= help: the trait `Debug` is not implemented for `MyStruct`
= note: add `#[derive(Debug)]` to `MyStruct` or manually `impl Debug for MyStruct`
読み方:
doesn't implement Debug: Debugトレイトが実装されていないcannot be formatted using {:?}: デバッグフォーマットが使えないnote: deriveするか手動実装するか
修正:
#![allow(unused)]
fn main() {
#[derive(Debug)] // これを追加
struct MyStruct {
value: i32,
}
}
エラーメッセージのパターン
パターン1: 所有権・借用関連
キーワード:
moved,borrow,mutable,immutabledoes not live long enough,lifetime
対処: Phase 2の内容を復習
パターン2: 型関連
キーワード:
mismatched types,expected,foundtrait bound is not satisfied
対処: 型を確認、deriveを追加
パターン3: 未定義・スコープ関連
キーワード:
cannot find,unresolvednot found in this scope
対処: import文の確認、スペルチェック
パターン4: 非同期関連
キーワード:
async,await,FutureSend,Sync
対処: async関数か確認、Send制約を満たす
デバッグ用ツール
型を調べる
#![allow(unused)]
fn main() {
// コンパイルエラーで型を教えてもらう
let x: () = some_expression;
// error: expected `()`, found `ActualType`
}
dbg!マクロ
#![allow(unused)]
fn main() {
let x = dbg!(some_expression);
// [src/main.rs:1] some_expression = value
}
cargo check
# コンパイルせずにエラーチェック(高速)
cargo check
clippy(リンター)
# より詳細な警告と提案
cargo clippy
まとめ
| 読むべき箇所 | 目的 |
|---|---|
| エラーコード | 詳細説明を調べる(rustc --explain) |
| 要約メッセージ | 何が問題かを把握 |
| コードスニペット | どこが問題かを特定 |
| 注釈(-や^) | 原因の詳細を理解 |
| help | 具体的な修正方法 |
心がけ:
- 最初のエラーから順に修正
- helpの提案を積極的に採用
- エラーコードで詳細を調べる
- 落ち着いて読む - Rustコンパイラは親切!