コンテンツにスキップ

Rustのエラー E0433: failed to resolve, use of undeclared type(未宣言の型)

E0433 は、HashMap::new() や rand::rng() のようなパスを書いたけれど、その最初の部分が何なのかを Rust が知らない、という意味のエラーです。ほとんどの場合、足りないのは1行だけです。use の行か、Cargo.toml の依存クレートか、mod の宣言のどれかです。うれしいことに、rustc はたいてい、そのままコピーできる行を表示してくれます。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。

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 で、直し方も同じです。

^^^^^^^ の印は、:: の前の部分である HashMap を指しています。HashMap::new() を呼ぶには、Rust はまず HashMap というものを見つける必要があります。2行目から見えるものをすべて調べましたが、その名前のものはありませんでした。だから、new を探し始めることさえできません。

大事なのは help: の行です。rustc は標準ライブラリを探して、std::collections の中に HashMap という構造体を見つけ、それを見えるようにする use の行を表示しています。1 + は「これを1行目として追加する」という意味です。

図書館の司書さんに、どの本かを言わずに「あの本の第3章をください」と頼むようなものです。第3章がある本はたくさんありますが、まずは本のタイトルがわからないと探せません。

どの 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());
}

実行結果:

アイテム数: 0
▶ 実際に試してみよう

Order::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 rand; を見かけるかもしれません。2018 エディション以降は不要です。クレートが Cargo.toml に入っていれば、そのまま使えます。extern crate を追加しても、E0433 は直りません。依存クレートがないままだと、エラーが E0463(can't find crate for rand、rand のクレートが見つからない)に変わるだけです。本当の直し方は cargo add です。

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 が示すインポートを追加するか、そのアイテムのドキュメントのページでパスを調べます。

  • E0432:同じ種類の問題が use の行で起きたもの。unresolved import(インポートを解決できない)。
  • E0425:(:: を使わない)値や関数が見つからない。つづりを間違えた変数などです。今の rustc は、let m: HashMap<&str, u32> のように型を書く位置で型が見つからないときにも E0425 を使います。古いバージョンではこれを E0412 と呼んでいました。同じ use の行で直ります。
  • E0599:型は見つかったけれど、:: のあとのメソッドやバリアントが存在しない。Light::Blue などです。
  • E0463:can't find crate(クレートが見つからない)。依存クレートがないのに extern crate を書いたときに出ます。
  • コンパイルエラーの一覧:エラー解説ページの全リストです。

理解度チェック

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