コンテンツにスキップ

Rustのエラー E0432: unresolved import(インポートを解決できない)

E0432 は、use の行のどれかが、Rust の見つけられないものを指している、という意味のエラーです。クレートがまだ Cargo.toml に入っていないのかもしれませんし、パスに小さなつづりの間違いがあるのかもしれません。あるいは、ファイルはあるのに、それがモジュールだと Rust が知らないのかもしれません。見た目は怖そうですが、ほとんどの場合は1行直すだけで解決しますし、どの行が問題なのかもたいていコンパイラが教えてくれます。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。

error[E0432]: unresolved import `rand`
--> src/main.rs:1:5
|
1 | use rand::random_range;
| ^^^^ use of unresolved module or unlinked crate `rand`
|
= help: if you wanted to use a crate named `rand`, use `cargo add rand` to add it to your `Cargo.toml`

「unresolved import rand」は「インポート rand を解決できない」という意味です。^^^^ の下のラベルは「解決できないモジュール、またはリンクされていないクレート rand を使っている」、help は「rand というクレートを使いたいなら、cargo add rand で Cargo.toml に追加してください」と言っています。

このエラーが出るのは、cargo new で作ったばかりで [dependencies] に何も書いていないプロジェクトの、次のプログラムです。

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("{roll}が出ました");
}

^^^^ の下に出る文言は、原因によって変わります。次のどれもが E0432 で、それぞれ下の別の直し方につながっています。

ラベルに出る文言 よくある原因 直し方
use of unresolved module or unlinked crate クレートが Cargo.toml にない、または mod の行がないファイル 直し方1か直し方3
could not find `collection` in `std` パスの途中のつづりの間違い 直し方2
no `Hashmap` in `collections` 最後の名前のつづり(または大文字・小文字)の間違い 直し方2
could not find `inventory` in the crate root 宣言していないモジュールへの crate:: のパス 直し方3
no external crate パスが間違ったモジュールから始まっている 直し方4

use の行は、ショートカットです。use rand::random_range; は「これから先、random_range と書いたら rand::random_range にあるもののことだよ」という意味です。このショートカットを作る前に、Rust はパスを1つずつたどる必要があります。まず rand を見つけ、次にその中の random_range を見つけます。

^^^^ の印が付いているのは、最初に失敗した部分です。ここでは先頭の rand なので、Rust は random_range を探すところまで進んでいません。help: の行は、その理由を推測しています。rand は crates.io のクレートなのに、このプロジェクトはまだそれを追加していない、ということです。

タクシーの運転手さんに「スプリングフェルド市のハーバー通り12番地」と住所を伝えたようなものです。市の名前が間違っていたら、運転手さんは通りを探し始めることさえできません。

Rust はすべてのパスを、プログラムを実行するときではなく、コンパイルするときに解決します。「念のため」に何かを読み込んでおくことはありません。コードから見えるのは、3種類のものだけです。Cargo.toml に書いたクレート(と std)、mod で宣言したモジュール、そしてそれらの中のアイテムです。use の行がその外にあるものを指していたら、Rust は推測したりせず、その場で止まります。

これはよいことです。Python や JavaScript では、インポートのつづりの間違いは、その行が実際に実行されたときに初めてエラーになることがよくあります。本番環境でかもしれません。Rust では、そもそもビルドできません。それに、追加していないクレートがプログラムにこっそり紛れ込むことも絶対にありません。

2018 エディション以降、use のパスは次のどれかから始まります。クレートの名前(std、rand)、crate(自分のクレートのルート)、self(現在のモジュール)、super(親モジュール)、または現在のモジュールで宣言したモジュールです。詳しくはモジュールのレッスンで、依存クレートについてはCargoとクレートで説明しています。

直し方1:cargo add でクレートを追加する

Section titled “直し方1:cargo add でクレートを追加する”

パスの最初の部分が rand、serde、regex のような crates.io のクレートで、help: の行に cargo add と書かれているときは、これを選びます。原因としてはこれがいちばん多く、ブログ記事からコードをコピーしたときは特によく起きます。Cargo.toml があるフォルダで、次のコマンドを実行しましょう。

Terminal window
cargo add rand

Cargo が最新のバージョンを探して、Cargo.toml に1行追加してくれます。

[dependencies]
rand = "0.10.3"

これで同じコードがビルドできるようになります。下のプログラムは、出た目そのものではなく、範囲に入っているかどうかを表示するので、実行結果がいつも同じになります。

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("出た目は1から6の範囲: {}", (1..=6).contains(&roll));
}

実行結果:

出た目は1から6の範囲: true
▶ 実際に試してみよう

ここでつまずきやすい点が2つあります。1つ目は、ダッシュを含むクレート名は、コードの中ではアンダースコアになることです。cargo add tracing-subscriber で追加しても、書くときは use tracing_subscriber::... です。2つ目は、クレートがワークスペースの依存関係になっていても、それを使うパッケージの Cargo.toml にも書く必要があることです。

ラベルに could not find `X` in `Y`(Y の中に X が見つからない)や no `X` in `Y`(Y に X はない)と出たときは、これを選びます。パスの途中か最後のどこかのつづりが間違っています。定番はこれです。

error[E0432]: unresolved import `std::collection`
--> src/main.rs:1:10
|
1 | use std::collection::HashMap;
| ^^^^^^^^^^ could not find `collection` in `std`

正しいモジュール名は、s の付いた collections です。名前は大文字と小文字も区別します。use std::collections::Hashmap; は no `Hashmap` in `collections` というエラーになり、rustc は help: a similar name exists in the module(モジュールに似た名前がある)と、正しいつづりを添えてくれます。直したインポートはこうです。

use std::collections::HashMap;
fn main() {
let mut stock: HashMap<&str, u32> = HashMap::new();
stock.insert("apples", 12);
println!("{:?}", stock.get("apples"));
}

実行結果:

Some(12)
▶ 実際に試してみよう

正しいパスがわからないときは、標準ライブラリのドキュメント(英語)で検索してみましょう。各アイテムのページのいちばん上に、フルパスが書かれています。この型についてはHashMapのページも見てください。

直し方3:mod でモジュールを宣言する

Section titled “直し方3:mod でモジュールを宣言する”

src/inventory.rs のような新しいファイルを作ったのに、use inventory::... がそれを見つけられないときは、これを選びます。Rust では、親のファイルが宣言するまで、ファイルはモジュールになりません。プロジェクトはこうなっています。

src/
├── main.rs use inventory::count_items; ← `mod inventory;` がない
└── inventory.rs pub fn count_items() -> u32 { 42 }

rustc は、何が足りないのかをはっきり教えてくれます。

error[E0432]: unresolved import `inventory`
--> src/main.rs:1:5
|
1 | use inventory::count_items;
| ^^^^^^^^^ use of unresolved module or unlinked crate `inventory`
|
help: to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module
|
1 + mod inventory;
|

help は「ソースファイル src/inventory.rs を使うには、このファイルで mod inventory と書いてモジュールを宣言してください」という意味です。src/main.rs(そのモジュールがライブラリのものなら src/lib.rs)の先頭に mod inventory; を追加しましょう。代わりに use crate::inventory::count_items; と書いても解決しません。モジュールがまだ宣言されていないので、could not find `inventory` in the crate root(クレートのルートに inventory が見つからない)というエラーになります。

Playground ではすべてが1つのファイルに入るので、ここではモジュールを mod inventory { ... } とその場で書いています。別ファイルにしたときとまったく同じように動きます。

mod inventory {
pub fn count_items() -> u32 {
42
}
}
use inventory::count_items;
fn main() {
println!("在庫の数: {}", count_items());
}

実行結果:

在庫の数: 42
▶ 実際に試してみよう

モジュールは、親の中で1回だけ宣言します。ほかのファイルからは use crate::inventory::... で使います。それを使うすべてのファイルに mod inventory; を書く必要はありません。

直し方4:パスを正しい場所から始める

Section titled “直し方4:パスを正しい場所から始める”

インポートがモジュールの中にあって、使いたいアイテムが自分のクレートの別のモジュールにあるときは、これを選びます。ここでは、shop の中にある receipt が、shop::store_name を使おうとしています。

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod receipt {
use store_name; // ❌ 探す場所が違う
pub fn header() -> String {
format!("== {} ==", store_name())
}
}
}
error[E0432]: unresolved import `store_name`
--> src/main.rs:7:13
|
7 | use store_name; // ❌ 探す場所が違う
| ^^^^^^^^^^ no external crate `store_name`

ラベルは「store_name という外部クレートはない」という意味です。use のパスの先頭に名前だけを書くと、「クレート、またはこのモジュールで宣言されたもの」という意味になります。store_name はそのどちらでもないので、Rust はその名前のクレートを探してしまいました。代わりに、どこから探し始めるのかを教えてあげましょう。

先頭に付けるもの 探し始める場所 例
crate:: 自分のクレートのルート(main.rs または lib.rs) use crate::shop::prices::price_of;
super:: 親モジュール use super::store_name;
self:: 現在のモジュール use self::lines::line;

3つすべてを1つのプログラムで使うと、こうなります。

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod prices {
pub fn price_of(item: &str) -> u32 {
if item == "apple" { 3 } else { 5 }
}
}
pub mod receipt {
use super::store_name; // 親モジュール:shop
use crate::shop::prices::price_of; // クレートのルートから
use self::layout::line; // このモジュールの子
mod layout {
pub fn line(item: &str, price: u32) -> String {
format!("{item}: {price}")
}
}
pub fn print(item: &str) {
println!("== {} ==", store_name());
println!("{}", line(item, price_of(item)));
}
}
}
fn main() {
shop::receipt::print("apple");
}

実行結果:

== Ferris Fruits ==
apple: 3
▶ 実際に試してみよう

ここでは use layout::line; と書いても動きます。layout は現在のモジュールで宣言されているからです。self:: は、それをはっきり書いているだけです。迷ったら、crate:: から始まるフルパスを書けば、クレートのどこからでも必ず使えます。rustc もよくこれを提案してくれます。help: a similar path exists(似たパスがある)のあとに、crate:: から始まるパスが表示されます。

古いバージョンのクレート向けに書かれたコード。 多くのチュートリアルは rand 0.8 を使っています。rand 0.10 では、こうなります。

error[E0432]: unresolved import `rand::thread_rng`
--> src/main.rs:1:5
|
1 | use rand::thread_rng;
| ^^^^^^^^^^^^^^^^ no `thread_rng` in the root

「ルートに thread_rng はない」という意味です。直し方:Cargo.toml に書いたバージョンのドキュメントを docs.rs で確認します。ここでは新しい名前は rand::rng() です。乱数のページも見てください。

main.rs と lib.rs の両方があるパッケージ。 この2つは別々のクレートです。main.rs の中では crate:: はバイナリのほうを指すので、lib.rs に pub mod inventory; があっても、use crate::inventory::count_items; は could not find `inventory` in the crate root になります。直し方:パッケージ名を使って use shop_app::inventory::count_items; と書きます(ダッシュはアンダースコアに変えます)。

アイテムはあるけれど非公開。 これは E0432 ではなく、別のエラー E0603 です。

error[E0603]: function `count_items` is private
--> src/main.rs:7:16
|
7 | use inventory::count_items;
| ^^^^^^^^^^^ private function

「関数 count_items は非公開」という意味です。直し方:fn の前に pub を付けます(途中にある mod にも付けます。非公開のモジュールがあると module `prices` is private になるからです)。詳しくはモジュールを見てください。

  • E0433:コードの中のパス(HashMap::new() や rand::rng() など)を解決できない。原因は同じですが、use の行ではない場所で起きます。
  • E0425:値や関数が見つからない。同じ use の行で直ることがよくあります。
  • E0603:インポートするものは見つかったけれど、非公開になっている。pub を付けます。
  • E0463:can't find crate(クレートが見つからない)。クレートが Cargo.toml にないのに extern crate rand; と書いたときに出ます。
  • コンパイルエラーの一覧:エラー解説ページの全リストです。

理解度チェック

1. 新しいプロジェクトに use serde::Serialize; をコピーしたら、クレート serde が unresolved または unlinked だという E0432 が出ました。直し方はどれですか?

2. src/billing.rs を作ったのに、main.rs の use billing::total; がエラーになります。何が足りないのですか?

3. mod shop { mod receipt { ... } } の中で、receipt が shop に直接定義された関数をインポートするにはどう書きますか?

スコア: 0 / 3