Rustのエラー E0433: failed to resolve, use of undeclared type(未宣言の型)
E0433 は、HashMap::new() や rand::rng() のようなパスを書いたけれど、その最初の部分が何なのかを Rust が知らない、という意味のエラーです。ほとんどの場合、足りないのは1行だけです。use の行か、Cargo.toml の依存クレートか、mod の宣言のどれかです。うれしいことに、rustc はたいてい、そのままコピーできる行を表示してくれます。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。
エラーメッセージ
Section titled “エラーメッセージ”error[E0433]: cannot find type `HashMap` in this scope --> src/main.rs:2:21 |2 | let mut stock = HashMap::new(); | ^^^^^^^ use of undeclared type `HashMap` |help: consider importing this struct |1 + use std::collections::HashMap; |1行目は「このスコープに型 HashMap が見つからない」、ラベルは「宣言されていない型 HashMap を使っている」という意味です。help は「この構造体をインポートしてはどうか」と提案しています。
このエラーが出るのは、次のプログラムです。
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}古いバージョンの Rust では、同じエラーが「failed to resolve: use of undeclared type HashMap」(解決に失敗:宣言されていない型 HashMap の使用)と表示されます。何が足りないかによっては、ラベルが use of undeclared type ではなく use of unresolved module or unlinked crate(クレートやモジュールの場合)になることもあります。これらはすべて E0433 で、直し方も同じです。
エラーの意味
Section titled “エラーの意味”^^^^^^^ の印は、:: の前の部分である HashMap を指しています。HashMap::new() を呼ぶには、Rust はまず HashMap というものを見つける必要があります。2行目から見えるものをすべて調べましたが、その名前のものはありませんでした。だから、new を探し始めることさえできません。
大事なのは help: の行です。rustc は標準ライブラリを探して、std::collections の中に HashMap という構造体を見つけ、それを見えるようにする use の行を表示しています。1 + は「これを1行目として追加する」という意味です。
図書館の司書さんに、どの本かを言わずに「あの本の第3章をください」と頼むようなものです。第3章がある本はたくさんありますが、まずは本のタイトルがわからないと探せません。
Rust がこうする理由
Section titled “Rust がこうする理由”どの Rust のファイルでも自動的に見える名前は、ほんの少しだけです。これをプレリュード(prelude)と呼びます。Vec、String、Option、Some、None、Result、Ok、Err、Box と、いくつかのトレイトです。HashMap、HashSet、fs、Ordering を含めて、それ以外はすべて use で持ち込むか、フルパスで書く必要があります。
こうしてプレリュードを小さく保つことで、名前の衝突を防いでいます。たとえば、標準ライブラリには2種類の Ordering 型がありますし、自分のコードにも Duration や Result があるかもしれません。Rust は、どれのことなのかを推測しません。ファイルの先頭で一度書いておけば、読む人の誰もが、それぞれの名前がどこから来たのかわかります。
クレートやモジュールも同じです。クレートは Cargo.toml に書いて初めて、モジュールは mod の行を書いて初めて、コードから存在するものになります。モジュールとCargoとクレートも見てください。
直し方1:rustc が提案する use の行を追加する
Section titled “直し方1:rustc が提案する use の行を追加する”help: に consider importing(インポートしてはどうか)と出たときは、これを選びます。直し方としては、これがずば抜けて多いです。提案された行を、ファイルの先頭にコピーしましょう。
use std::collections::HashMap;
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}実行結果:
Some(12)もう1つの方法は、呼び出す場所でフルパスの std::collections::HashMap::new() と書くことです。これでも動きますが、使うたびに毎回書かなければならないので、ふつうは use の行を選びます。この型についてはHashMapのページで詳しく説明しています。
rustc がいくつものインポートを提案してきたとき(consider importing one of these)は、選ぶ前によく読みましょう。名前が同じだけの別々の型で、自分が使いたいのはそのうちの1つだけです。
直し方2:型の名前を直すか、型を宣言する
Section titled “直し方2:型の名前を直すか、型を宣言する”その名前が自分で作った型のときは、これを選びます。help: がまったく出ないなら、その型はまだ存在していません。つづりの間違いなら、rustc が似た名前を教えてくれます。
error[E0433]: cannot find type `Invetory` in this scope --> src/main.rs:12:17 |12 | let stock = Invetory::new(); | ^^^^^^^^ use of undeclared type `Invetory` |help: a struct with a similar name exists |12 | let stock = Inventory::new(); | +help は「似た名前の構造体がある」という意味で、行の下の + が足りない1文字の位置を示しています。つづりを直しましょう。
struct Inventory { items: Vec<String>,}
impl Inventory { fn new() -> Self { Inventory { items: Vec::new() } }}
fn main() { let stock = Inventory::new(); println!("アイテム数: {}", stock.items.len());}実行結果:
アイテム数: 0Order::new() で提案なしの E0433 が出たら、struct Order をまだ書いていない(または、mod で宣言していないファイルの中にある)ということです。大文字・小文字も確認しましょう。inventory::new() と Inventory::new() は別の名前です。
直し方3:型があるモジュールの名前を書く
Section titled “直し方3:型があるモジュールの名前を書く”型や列挙型がモジュールの中で定義されていて、それをモジュールの外から使うときは、これを選びます。ここでは列挙型が mod traffic の中にあるのに、main で Light::Green と書いています。
error[E0433]: cannot find type `Light` in this scope --> src/main.rs:11:15 |11 | let now = Light::Green; | ^^^^^ use of undeclared type `Light` |help: consider importing this enum | 1 + use crate::traffic::Light; |help は「この列挙型をインポートしてはどうか」と提案しています。列挙型をインポートしましょう(または traffic::Light::Green と書きます)。インポートするのは列挙型で、それぞれのバリアントは、そのあとも Light::Green と書くことに注意してください。
mod traffic { #[derive(Debug)] pub enum Light { Red, Yellow, Green, }}
use crate::traffic::Light;
fn can_go(light: &Light) -> bool { match light { Light::Green => true, Light::Yellow | Light::Red => false, }}
fn main() { let now = Light::Green; println!("{now:?}: 進める = {}", can_go(&now));}実行結果:
Green: 進める = trueバリアントのパスは、ちょうど2つの部分からなります。Enum::Variant です。Light::Red::Green のように1つ多く書くと、cannot find module `Red` in `Light` (Light の中にモジュール Red が見つからない)という E0433 になり、ラベルには `Red` is a variant, not a module(Red はモジュールではなくバリアント)と出ます。列挙型も見てください。
直し方4:クレートを追加するか、モジュールを宣言する
Section titled “直し方4:クレートを追加するか、モジュールを宣言する”ラベルに use of unresolved module or unlinked crate と出たときは、これを選びます。パスの最初の部分が、Rust の知らないクレートかモジュールです。
error[E0433]: cannot find module or crate `rand` in this scope --> src/main.rs:4:19 |4 | let mut rng = rand::rng(); | ^^^^ 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`「このスコープにモジュールまたはクレート rand が見つからない」という意味で、help は「rand というクレートを使いたいなら、cargo add rand で Cargo.toml に追加してください」と言っています。crates.io のクレートなら、プロジェクトのフォルダで cargo add rand を実行します。fs のような標準ライブラリのモジュールなら、rustc は代わりに use std::fs; を提案します。そして src/inventory.rs のような自分のファイルなら、help に to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module(ソースファイル src/inventory.rs を使うには、このファイルで mod inventory と書いてモジュールを宣言してください)と出ます。
src/├── main.rs inventory::count_items() ← 先頭に `mod inventory;` が必要└── inventory.rs pub fn count_items() -> u32 { 42 }Playground で動くように、モジュールをその場で書いて1つのファイルにまとめると、こうなります。
mod inventory { pub fn count_items() -> u32 { 42 }}
fn main() { println!("在庫の数: {}", inventory::count_items());}実行結果:
在庫の数: 42別ファイルにするときの違いは、mod inventory { ... } が mod inventory; になり、中身が src/inventory.rs に移ることだけです。
extern crate はどうなの?
Section titled “extern crate はどうなの?”古いコードでは extern crate rand; を見かけるかもしれません。2018 エディション以降は不要です。クレートが Cargo.toml に入っていれば、そのまま使えます。extern crate を追加しても、E0433 は直りません。依存クレートがないままだと、エラーが E0463(can't find crate for rand、rand のクレートが見つからない)に変わるだけです。本当の直し方は cargo add です。
よく出会う場面
Section titled “よく出会う場面”cmp で比較するとき。 match a.cmp(&b) で Ordering::Less のアームを書くと E0433 になり、rustc は use std::cmp::Ordering; と use std::sync::atomic::Ordering; の2つのインポートを提案します。使いたいのは std::cmp::Ordering です。atomic のほうはスレッド用です。matchも見てください。
mod tests ブロックの中のテスト。 テストモジュールは子モジュールなので、インポートしないと自分の型が見えません。mod tests の中で Inventory::new() と書くと、help: consider importing this struct と use crate::Inventory; が添えられた E0433 になります。直し方:テストモジュールの先頭に use super::*; を書きます。テストも見てください。
ドキュメントやブログ記事から貼り付けたコード。 サンプルコードでは、use の行が省かれていることがよくあります。fs::read_to_string(...) は cannot find module or crate `fs` in this scope になり、help に use std::fs; と出ます。直し方:rustc が示すインポートを追加するか、そのアイテムのドキュメントのページでパスを調べます。
関連するエラー
Section titled “関連するエラー”- E0432:同じ種類の問題が
useの行で起きたもの。unresolved import(インポートを解決できない)。 - E0425:(
::を使わない)値や関数が見つからない。つづりを間違えた変数などです。今の rustc は、let m: HashMap<&str, u32>のように型を書く位置で型が見つからないときにも E0425 を使います。古いバージョンではこれを E0412 と呼んでいました。同じuseの行で直ります。 - E0599:型は見つかったけれど、
::のあとのメソッドやバリアントが存在しない。Light::Blueなどです。 - E0463:
can't find crate(クレートが見つからない)。依存クレートがないのにextern crateを書いたときに出ます。 - コンパイルエラーの一覧:エラー解説ページの全リストです。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. Vec::new() はインポートなしで動くのに、HashSet::new() が E0433 になるのはなぜですか?
2. match a.cmp(&b) に対して、rustc が use std::cmp::Ordering; と use std::sync::atomic::Ordering; の両方を提案しました。どちらを選びますか?
3. rand::rng() が、ラベルに「use of unresolved module or unlinked crate」と出る E0433 になりました。どうすれば直りますか?
スコア: 0 / 3
さらに詳しく
Section titled “さらに詳しく”- E0433 — Rust error codes index(英語):このエラーの公式の説明です。宣言されていない型と、リンクされていないクレートの両方の場合が載っています。
- useキーワードでパスをスコープに持ち込む — The Rust Programming Language 日本語版:
useのしくみと、HashMapのような型をインポートするのがふつうである理由がわかります。 - モジュールツリーの要素を示すためのパス — The Rust Programming Language 日本語版:フルパス、
crate::、super::の使い方です。 std::prelude— 標準ライブラリのドキュメント(英語):useなしで見える名前の正確な一覧です。- Path and module changes in Rust 2018 — Edition Guide(英語):
extern crateがもう必要ない理由がわかります。