Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

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();
  |               ++++++++

各部分の説明

  1. エラーコード: error[E0382]

    • E0382 は一意のエラーコード
    • rustc --explain E0382 で詳細な説明が見られる
  2. エラーの要約: borrow of moved value: 's'

    • 何が問題かの簡潔な説明
  3. ファイル位置: --> src/main.rs:4:20

    • ファイル名:行番号:列番号
  4. コードスニペット: エラー箇所のコードと注釈

    • | の後にコードが表示される
    • ^- でエラー箇所を指示
    • 追加の説明が付く
  5. 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

読み方:

  1. mismatched types: 型が一致しない
  2. expected i32, found &str: i32を期待したが&strがあった
  3. 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

読み方:

  1. cannot borrow as mutable: 可変借用できない
  2. immutable borrow occurs here: 行3で不変借用
  3. mutable borrow occurs here: 行4で可変借用しようとした
  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 {
  |           ++++     ++          ++          ++

読み方:

  1. missing lifetime specifier: ライフタイム指定子がない
  2. help: 戻り値が借用値だが、xyのどちらか不明
  3. 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`

読み方:

  1. doesn't implement Debug: Debugトレイトが実装されていない
  2. cannot be formatted using {:?}: デバッグフォーマットが使えない
  3. note: deriveするか手動実装するか

修正:

#![allow(unused)]
fn main() {
#[derive(Debug)]  // これを追加
struct MyStruct {
    value: i32,
}
}

エラーメッセージのパターン

パターン1: 所有権・借用関連

キーワード:

  • moved, borrow, mutable, immutable
  • does not live long enough, lifetime

対処: Phase 2の内容を復習

パターン2: 型関連

キーワード:

  • mismatched types, expected, found
  • trait bound is not satisfied

対処: 型を確認、deriveを追加

パターン3: 未定義・スコープ関連

キーワード:

  • cannot find, unresolved
  • not found in this scope

対処: import文の確認、スペルチェック

パターン4: 非同期関連

キーワード:

  • async, await, Future
  • Send, 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具体的な修正方法

心がけ:

  1. 最初のエラーから順に修正
  2. helpの提案を積極的に採用
  3. エラーコードで詳細を調べる
  4. 落ち着いて読む - Rustコンパイラは親切!