Ошибка Rust E0433: failed to resolve, use of undeclared type (тип не найден)
E0433 значит, что ты написал путь вроде HashMap::new() или rand::rng(), а Rust не знает, что такое его первая часть. Почти всегда не хватает одной строки: use, зависимости в Cargo.toml или объявления mod. Хорошая новость: обычно rustc сам печатает эту строку, остаётся её скопировать. Эта страница — часть руководства по ошибкам компилятора.
Сообщение об ошибке
Заголовок раздела «Сообщение об ошибке»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; |Компилятор пишет: в этой области видимости нет типа HashMap, и предлагает импортировать структуру строкой use std::collections::HashMap;. Вот программа, которая выдаёт эту ошибку:
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}Старые версии Rust печатают ту же ошибку как «failed to resolve: use of undeclared type HashMap». В зависимости от того, чего не хватает, подпись может говорить и use of unresolved module or unlinked crate (для крейта или модуля) вместо use of undeclared type. Всё это E0433, и исправляется всё одинаково.
Что это значит
Заголовок раздела «Что это значит»^^^^^^^ указывает на HashMap — часть до ::. Чтобы вызвать HashMap::new(), Rust сначала должен найти что-то по имени HashMap. Он посмотрел на всё, что видно из строки 2, и ничего с таким именем не нашёл, поэтому даже не начал искать new.
Самое важное — строка help:. rustc поискал в стандартной библиотеке, нашёл структуру HashMap в std::collections и показывает строку use, которая сделает её видимой. 1 + значит «добавь это как строку 1».
Это как попросить библиотекаря принести «третью главу той самой книги» и не сказать, какой. Третья глава есть во многих книгах, но сначала нужно название.
Почему Rust так делает
Заголовок раздела «Почему Rust так делает»Автоматически в каждом файле Rust видно лишь небольшое число имён. Этот набор называется прелюдией (prelude): Vec, String, Option, Some, None, Result, Ok, Err, Box и несколько трейтов. Всё остальное, включая HashMap, HashSet, fs и Ordering, нужно подключать через use или писать с полным путём.
Так прелюдия остаётся маленькой, а имена не конфликтуют. Например, в стандартной библиотеке есть два разных типа Ordering, а в твоём коде тоже может оказаться свой Duration или Result. Rust не будет угадывать, какой ты имел в виду. Ты говоришь это один раз в начале файла, и любой читатель видит, откуда берётся каждое имя.
С крейтами и модулями то же самое: крейт существует для твоего кода, только когда он указан в Cargo.toml, а модуль — только после строки mod. Подробнее в уроках Модули и Cargo и крейты.
Как исправить
Заголовок раздела «Как исправить»Исправление 1: добавь строку use, которую предлагает rustc
Заголовок раздела «Исправление 1: добавь строку use, которую предлагает rustc»Выбирай это, когда help: говорит consider importing (попробуй импортировать). Это самое частое исправление. Скопируй предложенную строку в начало файла:
use std::collections::HashMap;
fn main() { let mut stock = HashMap::new(); stock.insert("яблоки", 12); println!("{:?}", stock.get("яблоки"));}Вывод:
Some(12)Другой вариант — полный путь прямо в месте вызова, std::collections::HashMap::new(). Это тоже работает, но его пришлось бы повторять везде, поэтому обычно пишут use. Подробнее об этом типе — в уроке HashMap.
Если rustc предлагает несколько импортов (consider importing one of these), прочитай их, прежде чем выбрать. Это разные типы с одинаковым именем, и нужен тебе только один из них.
Исправление 2: исправь имя типа или объяви тип
Заголовок раздела «Исправление 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(); | +Подсказка говорит, что есть структура с похожим именем, а + под строкой показывает пропущенную букву. Исправь написание:
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: укажи модуль, в котором живёт тип
Заголовок раздела «Исправление 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; |Импортируй перечисление (или пиши 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Путь к варианту состоит ровно из двух частей: Enum::Variant. Если написать на одну часть больше, например Light::Red::Green, получишь E0433 с cannot find module `Red` in `Light` и подписью `Red` is a variant, not a module (Red — это вариант, а не модуль). Подробнее в уроке Перечисления.
Исправление 4: добавь крейт или объяви модуль
Заголовок раздела «Исправление 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`Здесь rustc не находит модуль или крейт rand и советует cargo add rand. Для крейта с crates.io запусти cargo add rand в папке проекта. Для модуля стандартной библиотеки, например fs, rustc вместо этого предложит use std::fs;. А для твоего собственного файла, скажем src/inventory.rs, подсказка говорит to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module (чтобы использовать этот файл, объяви модуль строкой mod inventory):
src/├── main.rs inventory::count_items() ← нужен `mod inventory;` в начале└── inventory.rs pub fn count_items() -> u32 { 42 }Вот та же программа в одном файле, с модулем прямо в коде, чтобы она запускалась в Playground:
mod inventory { pub fn count_items() -> u32 { 42 }}
fn main() { println!("Товаров на складе: {}", inventory::count_items());}Вывод:
Товаров на складе: 42С отдельным файлом меняется только одно: mod inventory { ... } превращается в mod inventory;, а тело переезжает в src/inventory.rs.
А как же extern crate?
Заголовок раздела «А как же extern crate?»В старом коде можно встретить extern crate rand;. Начиная с редакции 2018 это не нужно: как только крейт указан в Cargo.toml, им можно пользоваться напрямую. Добавление extern crate не исправляет E0433. Без зависимости ошибка просто сменится на E0463, can't find crate for rand. Настоящее исправление — cargo add.
Где это обычно встречается
Заголовок раздела «Где это обычно встречается»Сравнение через cmp. match a.cmp(&b) с ветками Ordering::Less даёт E0433, и rustc предлагает два импорта: use std::cmp::Ordering; и use std::sync::atomic::Ordering;. Тебе нужен std::cmp::Ordering; атомарный — для потоков. Подробнее в уроке Match.
Тесты в блоке mod tests. Модуль тестов — дочерний модуль, поэтому он не видит твои типы, пока ты их не импортируешь. Inventory::new() внутри mod tests даёт E0433 с help: consider importing this struct и use crate::Inventory;. Исправление: напиши use super::*; в начале модуля тестов. Подробнее в уроке Тестирование.
Код, вставленный из документации или блога. В примерах часто пропущены строки use. fs::read_to_string(...) падает с cannot find module or crate `fs` in this scope и подсказкой use std::fs;. Исправление: добавь импорт, который показывает rustc, или посмотри путь элемента на его странице в документации.
Связанные ошибки
Заголовок раздела «Связанные ошибки»- E0432: та же проблема, но в строке
use,unresolved import. - E0425: не найдено значение или функция (без
::), например переменная с опечаткой. Нынешний rustc использует E0425 и для отсутствующего типа в позиции типа, напримерlet m: HashMap<&str, u32>; старые версии называют это E0412. Исправляется той же строкойuse. - E0599: тип нашёлся, но метода или варианта после
::не существует, напримерLight::Blue. - E0463:
can't find crate, из-заextern crateбез зависимости. - Все ошибки компилятора: полный список страниц с ошибками.
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
1. Почему HashSet::new() даёт E0433, а Vec::new() работает без всякого импорта?
2. Для твоего match a.cmp(&b) rustc предлагает и use std::cmp::Ordering;, и use std::sync::atomic::Ordering;. Что выбрать?
3. rand::rng() даёт E0433 с подписью «use of unresolved module or unlinked crate». Что это исправит?
Результат: 0 / 3
Что почитать
Заголовок раздела «Что почитать»- E0433 — список кодов ошибок Rust (на английском): официальное объяснение, со случаями необъявленного типа и неподключённого крейта.
- Введение путей в область видимости с помощью ключевого слова use — книга «Язык программирования Rust» (перевод на русский): как работает
useи почему типы вродеHashMapпринято импортировать. - Пути для ссылки на элемент в дереве модулей — книга «Язык программирования Rust» (перевод на русский): полные пути,
crate::иsuper::. std::prelude— документация стандартной библиотеки (на английском): точный список имён, которые видны безuse.- Path and module changes in Rust 2018 — Edition Guide (на английском): почему
extern crateбольше не нужен.