コンテンツにスキップ

Rustのエラー E0601: `main` function not found in crate(main関数が見つからない)

E0601 は、Rust がプログラムをビルドしようとしたのに、どこから始まるのかが見つからなかった、という意味のエラーです。Rust のプログラムはどれも、src/main.rs のトップレベルに書かれた、ちょうど main という名前の関数から始まります。それがない、つづりが違う、モジュールの中に入っている、という場合にこのエラーが出ます。チュートリアルやライブラリのドキュメントからコードの一部をコピーしたときによく起こりますが、直すのはいつも簡単です。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。

error[E0601]: `main` function not found in crate `main`
--> src/main.rs:7:2
|
7 | } // ❌ end of the file, and no `fn main` anywhere
| ^ consider adding a `main` function to `src/main.rs`

「main function not found in crate main」は「クレート main に main 関数が見つからない」、「consider adding a main function to src/main.rs」は「src/main.rs に main 関数を追加してはどうか」という意味です。

このエラーが出るのは、次のプログラムです。

fn total(prices: &[u32]) -> u32 {
prices.iter().sum()
}
fn average(prices: &[u32]) -> u32 {
total(prices) / prices.len() as u32
} // ❌ end of the file, and no `fn main` anywhere

コメントは「ファイルの終わり。fn main はどこにもない」という意味です(エラーになる例なので、コードはそのままにしています)。

^ はファイルのいちばん最後、最後の } のすぐあとを指しています。変に見えますが、理由があります。rustc は fn main を探してファイル全体を読み、見つからないまま最後まで来てしまったのです。指すべき間違った行はありません。問題は、そこにない行なのです。

メッセージの中のクレート名は、ビルドのしかたによって変わります。この出力は rustc src/main.rs で出したものなので、クレートはファイル名から main と呼ばれています。cargo run なら、Cargo.toml のパッケージ名が表示されます。たとえば `main` function not found in crate `shop` のようにです。エラーも直し方も同じです。

すばらしい場面がそろっているのに、「第1幕 第1場」がない芝居の台本のようなものです。役者の準備はできていても、劇がどこから始まるのか誰にもわかりません。

Rust のバイナリ(実行するプログラム)には、決まった入口が1つ必要です。プログラムを起動すると、OS が main を呼び、ほかのことはすべて main が呼ぶから起こります。Rust は推測しません。ファイルの最初の関数でも、start という名前の関数でも、Main でもだめです。名前はちょうど main、全部小文字で、クレートのトップレベルになければなりません。

それだけでは動くプログラムにならないコード、たとえばほかのコードから使われるヘルパーの集まりは、ライブラリです。ライブラリには main がなく、代わりに src/lib.rs に書きます。E0601 が出たとき、実はコードには問題がなく、クレートの種類が間違っているだけ、ということもよくあります。詳しくはバイナリクレートとライブラリクレートを一緒に使うとコードを理解しようを見てください。

直し方1:main 関数を追加する(またはつづりを直す)

Section titled “直し方1:main 関数を追加する(またはつづりを直す)”

たいていはこれを選びます。どこかから関数をコピーしてきた、またはヘルパーを書き始めたけれど、まだ main を書いていない、という場合です。fn main() を追加して、そこから自分のコードを呼びましょう。

fn total(prices: &[u32]) -> u32 {
prices.iter().sum()
}
fn average(prices: &[u32]) -> u32 {
total(prices) / prices.len() as u32
}
fn main() { // ✅ プログラムはここから始まる
let prices = [250, 199, 1200];
println!("total: {} cents", total(&prices));
println!("average: {} cents", average(&prices));
}

実行結果:

total: 1649 cents
average: 549 cents
▶ 実際に試してみよう

もう main があるなら、つづりを確かめましょう。fn Main()、fn mian()、fn main_() は、どれもまったく同じ E0601 になります。Rust から見れば、ただの別の関数だからです。名前は大文字と小文字を区別しますし、かっこの付いた fn main() という関数でなければなりません。

直し方2:main をモジュールの外に出す

Section titled “直し方2:main をモジュールの外に出す”

メッセージに the main function must be defined at the crate level(main 関数はクレートのレベルで定義しなければならない)とあるときは、これを選びます。main はあるのですが、mod の中にあるので、実際には app::main であって、プログラムの入口ではありません。

error[E0601]: `main` function not found in crate `main`
--> src/main.rs:5:2
|
5 | }
| ^ the main function must be defined at the crate level (in `src/main.rs`)
|
note: here is a function named `main`
--> src/main.rs:2:5
|
2 | pub fn main() { // ❌ inside a module, not at the top level
| ^^^^^^^^^^^^^
= note: you have one or more functions named `main` not defined at the crate level
= help: consider moving the `main` function definitions

note は「main という名前の関数はここにある」「クレートのレベルで定義されていない main という関数が1つ以上ある」、help は「main 関数の定義を移動してはどうか」という意味です。

このエラーが出るプログラムです(コメントは「モジュールの中で、トップレベルではない」という意味です)。

mod app {
pub fn main() { // ❌ inside a module, not at the top level
println!("Starting the shop...");
}
}

本物の main をトップレベルに置きましょう。モジュールの中のコードはそのままでかまいません。run のようなわかりやすい名前を付けて、main から呼びます。

mod app {
pub fn run() {
println!("Starting the shop...");
}
}
fn main() { // ✅ src/main.rs のトップレベルにある
app::run();
}

実行結果:

Starting the shop...
▶ 実際に試してみよう

別のファイルにあるモジュールでも同じです。src/app.rs の中の pub fn main() は app::main であって、決してプログラムの入口にはなりません。詳しくはモジュールを見てください。

直し方3:単独で動かすものでないなら、ライブラリにする

Section titled “直し方3:単独で動かすものでないなら、ライブラリにする”

コードがほかのコードから使われるヘルパーの集まりで、「実行する」ものが何もないときは、これを選びます。ライブラリには main がありません。--lib を付けてプロジェクトを作りましょう。

Terminal window
cargo new --lib cart # src/lib.rs を作る:ライブラリなので main はいらない
cargo new shop # fn main() のある src/main.rs を作る:プログラム

ヘルパーは src/lib.rs に書き、ほかのコードに使わせたいものに pub を付けます。確認は cargo run ではなくテストで行います。

src/lib.rs
pub fn total(prices: &[u32]) -> u32 {
prices.iter().sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn adds_prices() {
assert_eq!(total(&[3, 4]), 7);
}
}

ライブラリには cargo build か cargo test を使います。ライブラリでは cargo run は動かず、error: a bin target must be available for `cargo run`(cargo run にはバイナリのターゲットが必要)と表示されます。Cargo なりの「このパッケージにはプログラムがない」という言い方です。両方欲しいなら、src/lib.rs の隣に src/main.rs を追加しましょう。ライブラリはパッケージ名で使います。

src/main.rs
fn main() {
let sum = cart::total(&[250, 199, 1200]);
println!("total: {} cents", sum);
}

これで cargo run は total: 1649 cents と表示します。詳しくはバイナリクレートとライブラリクレートを一緒に使うとテストを見てください。

ドキュメントやチュートリアルのコードを貼り付けたとき。 例の多くは、プログラム全体ではなく、関数や struct だけを載せています。それを src/main.rs に貼り付けると、E0601 になります。直し方:実際に何かをする行を fn main() { ... } で包み、関数や構造体はその外に置きます(Rust Playground は main がないことに気づいて、実行する代わりにビルドすることを提案してくれるので、そこではふつうこのエラーは見ません)。

エディタが main.rs の最後の行を赤くする。 rust-analyzer は裏で cargo check を実行しているので、まだヘルパーを書いている途中でも、最後の行に E0601 が表示されます。心配はいりません。fn main() を追加すれば、すぐに消えます。

src/bin/ の中の追加のプログラム。 src/bin/import.rs のような src/bin/ の中のファイルは、どれも別々のプログラムなので、それぞれに fn main() が必要です。直し方:そのファイルに main を追加するか、共通のコードを src/lib.rs に移します。下の Cargo Targets のリンクを見てください。

  • E0425:cannot find value in this scope。プログラムのどこか別の場所で名前のつづりを間違えた。たとえば totl() を呼んだとき。
  • E0433:failed to resolve。main.rs からモジュールやライブラリクレートが見つからない。たとえば、パッケージ名を間違えて cart::total と書いたとき。
  • E0603:item is private。main からライブラリの関数は見つかったが、pub が付いていない。
  • E0463:can’t find crate。use したクレートが Cargo.toml に入っていない。
  • コンパイルエラーの一覧:エラー解説ページの全リストです。

理解度チェック

1. src/main.rs に fn Main() { ... } があります。cargo run は何と言いますか?

2. ほかのコードから使うヘルパーを書いていて、実行するものは何もありません。正しい構成はどれですか?

3. rustc が「the main function must be defined at the crate level」と言いました。何が問題ですか?

スコア: 0 / 3