Перейти к содержимому

Ошибка 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 видно лишь небольшое число имён. Этот набор называется прелюдией (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 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