問題点
Rustは、PythonやJavaScriptのような言語とは異なる方法でモジュールを処理します。Rustにおいて、modキーワードは単にコードをインポートするだけではありません。モジュールが存在することを「宣言」するものです。main.rsにmod auth;と記述すると、コンパイラに対してauthモジュールのコードを含むファイルを探しに行くよう指示することになります。コンパイラが想定されるディレクトリを探索してもファイルが見つからない場合、**error[E0583]**が発生します。
このエラーは、いわば「連絡の不備」のようなものと考えてください。プログラムの新しいパーツが存在することを宣言したものの、その実体となる物理ファイルをコンパイラに提供していない状態です。これは通常、200行ほどあるmain.rsからコードを切り出し、初めて専用のファイルに移動させるときによく起こります。
error[E0583]: file not found for module `my_module`
help: to create the module `my_module`, create file "src/my_module.rs" or "src/my_module/mod.rs"
素早い解決策
コンパイラの出力には、実際には修正のためのロードマップが示されています。2つの具体的なファイルパスが提案されます。コードをどのように整理したいかに応じて、以下の2つの構造のいずれかを選択してください。
1. フラットな構成(ほとんどの場合に推奨)
モダンなRust(Edition 2018以降)では、モジュールをsrc/ディレクトリ内の独立したファイルとして保持することが好まれます。モジュール名がauthであれば、単にauth.rsを作成するだけです。
プロジェクト構造:
my_project/
├── Cargo.toml
└── src/
├── main.rs
└── auth.rs <-- このファイルを作成
main.rs内での宣言はシンプルなままです:
mod auth; // Rustは自動的にsrc/auth.rsを探します
2. フォルダによる構成(複雑なモジュール向け)
モジュールが大きくなりすぎて、1つのファイルでは収まらなくなることがあります。もしauthモジュールに独自のサブモジュール(auth::samlやauth::oauthなど)が必要な場合は、フォルダを使用します。authという名前のディレクトリを作成し、その中にmod.rsファイルを配置します。
プロジェクト構造:
my_project/
├── Cargo.toml
└── src/
├── main.rs
└── auth/
└── mod.rs <-- これがモジュールのエントリポイントとして機能します
Rustはsrc/auth/mod.rsをsrc/auth.rsと同等として扱います。
ネストされたモジュールの扱い
モジュールをネストさせると複雑さが増します。例えば、特定のコネクタを持つデータベースモジュールdb::connectorがあるとしましょう。
src/db.rsの中でmod connector;を宣言した場合、コンパイラはそのファイルがdbモジュールからの相対パスにあることを期待します。ファイルパスには以下の2つの有効な選択肢があります:
- 選択肢 A:
src/db/connector.rs(モダンでクリーンなスタイル) - 選択肢 B:
src/db/connector/mod.rs(古い階層的なスタイル)
よくある間違いは、connector.rsをsrc/フォルダに直接配置してしまうことです。これは失敗します。Rustでは、サブモジュールは親モジュールの名前が付いたサブディレクトリ内に存在する必要があります。
一般的なデバッグのチェックリスト
隠れた拡張子に注意
ファイルの末尾が正確に.rsであることを確認してください。基本的なテキストエディタは、時として末尾に.txtをこっそり追加することがあります。Windowsでは、「登録されている拡張子は表示しない」設定が有効になっていると、auth.rs.txtという名前のファイルがauth.rsとして表示されることがあります。これが疑われる場合は、ターミナルでlsやdirを使用してファイル名を確認してください。
大文字・小文字の区別を遵守する
Rustは厳密に大文字と小文字を区別します。コードでmod Database;と書いていても、ファイル名がdatabase.rsであれば、LinuxやmacOSではコンパイラがエラーになります。これらのオペレーティングシステムは、大文字・小文字を区別するファイルシステムを使用しているためです。混乱を避けるため、ファイル名とモジュール宣言の両方で常にsnake_caseを使用してください。
宣言はトップレベルに保つ
Rustでは関数内でモジュールを宣言することも可能ですが、それが良いアイデアであることは稀です。そうすると、パス解決のルールが混乱を招く原因になります。modステートメントは、main.rsまたはlib.rsファイルの先頭に配置するようにしましょう。
修正の確認
エラーが修正されたかどうかを確認するために、フルビルドを待つ必要はありません。代わりにクイックチェックを実行しましょう:
cargo check
このコマンドは、実行ファイルを生成するオーバーヘッドなしにコードを解析します。小規模なプロジェクトであれば、通常2秒以内に終了します。エラーが解消されない場合は、エラーメッセージ内のパスと実際のファイルパスを1文字ずつ比較してください。コンパイラがsrc/api/routes.rsを求めている場合は、誤ってsrc/routes.rsに配置していないか確認してください。
重要なポイント
modは単なるインポートではなく「宣言」です。これはRustにファイルを探すよう指示します。- ファイルシステムは、モジュールの階層構造を完璧に反映している必要があります。
- プロジェクトのレイアウトをスッキリさせるために、
name/mod.rs形式よりもname.rs形式を優先しましょう。 - クロスプラットフォームの互換性を維持するために、ファイル名には常に
snake_caseを使用してください。

