Ошибка Rust E0432: unresolved import (импорт не найден)
E0432 значит, что одна из твоих строк use указывает на то, что Rust не может найти. Может быть, крейта ещё нет в Cargo.toml, может быть, в пути маленькая опечатка, а может быть, файл существует, но 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`Компилятор сообщает: импорт rand не разрешён, такого модуля или подключённого крейта нет, и советует добавить крейт командой cargo add rand. Вот программа, которая выдаёт эту ошибку в свежем проекте cargo new, где в [dependencies] пусто:
use rand::random_range;
fn main() { let roll = random_range(1..=6); println!("You rolled {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 проходит путь по частям: сначала ищет rand, потом random_range внутри него.
^^^^ отмечает первую часть, которую найти не удалось. Здесь это rand, самый первый сегмент, так что до random_range Rust даже не дошёл. Строка help: предполагает причину: rand — это крейт с crates.io, а проект его не добавил.
Это как назвать таксисту адрес «ул. Портовая, 12, город Спрингфелд». Если название города неверное, водитель даже не начнёт искать улицу.
Почему Rust так делает
Заголовок раздела «Почему Rust так делает»Rust разрешает каждый путь во время компиляции, а не во время работы программы. Ничего не загружается «на всякий случай». Твой код видит только три вида вещей: крейты из Cargo.toml (плюс std), модули, которые ты объявил через mod, и то, что лежит внутри них. Если строка use называет что-то за пределами этого набора, Rust сразу останавливается и не пытается угадать.
И это хорошо. Импорт с опечаткой в Python или JavaScript часто падает, только когда эта строка наконец выполнится, — возможно, уже в продакшене. В Rust такой код просто не соберётся. А ещё это значит, что крейт, который ты не добавлял, никогда не проберётся в твою программу.
Начиная с редакции 2018, путь в use начинается в одном из таких мест: имя крейта (std, rand), crate (корень твоего собственного крейта), self (текущий модуль), super (родительский модуль) или модуль, объявленный в текущем модуле. Подробно это разобрано в уроке Модули, а про зависимости рассказывает урок Cargo и крейты.
Как исправить
Заголовок раздела «Как исправить»Исправление 1: добавь крейт через cargo add
Заголовок раздела «Исправление 1: добавь крейт через cargo add»Выбирай это, когда первый сегмент — крейт с crates.io, например rand, serde или regex, а строка help: упоминает cargo add. Это самая частая причина, особенно когда копируешь код из статьи в блоге. Запусти это в папке, где лежит Cargo.toml:
cargo add randCargo находит самую новую версию и сам добавляет строку в Cargo.toml:
[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Здесь люди часто спотыкаются о две вещи. Во-первых, в коде имена крейтов с дефисом пишутся через подчёркивание: ты делаешь cargo add tracing-subscriber, но пишешь use tracing_subscriber::.... Во-вторых, если крейт — зависимость твоего рабочего пространства (workspace), его всё равно нужно указать в Cargo.toml того пакета, который его использует.
Исправление 2: исправь написание пути
Заголовок раздела «Исправление 2: исправь написание пути»Выбирай это, когда подпись говорит could not find `X` in `Y` или no `X` in `Y`. Что-то в середине или в конце пути написано с ошибкой. Классический пример:
error[E0432]: unresolved import `std::collection` --> src/main.rs:1:10 |1 | use std::collection::HashMap; | ^^^^^^^^^^ could not find `collection` in `std`Модуль называется collections, с s на конце. Регистр букв тоже важен: 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("яблоки", 12); println!("{:?}", stock.get("яблоки"));}Вывод:
Some(12)Если не уверен в точном пути, поищи в документации стандартной библиотеки (на английском). На странице каждого элемента вверху указан его полный путь. Подробнее об этом типе — в уроке HashMap.
Исправление 3: объяви модуль через mod
Заголовок раздела «Исправление 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; |Подсказка говорит: чтобы использовать файл src/inventory.rs, объяви модуль строкой mod inventory в этом файле. Добавь mod inventory; в начало src/main.rs (или src/lib.rs, если модуль относится к твоей библиотеке). Если вместо этого написать use crate::inventory::count_items;, это не поможет: будет ошибка could not find `inventory` in the crate root, потому что модуль всё ещё не объявлен.
В Playground всё лежит в одном файле, поэтому здесь модуль написан прямо в коде через mod inventory { ... }. Работает он точно так же, как отдельный файл:
mod inventory { pub fn count_items() -> u32 { 42 }}
use inventory::count_items;
fn main() { println!("Товаров на складе: {}", count_items());}Вывод:
Товаров на складе: 42Объявляй каждый модуль один раз, в его родителе. Другие файлы добираются до него через use crate::inventory::.... Не добавляй mod inventory; в каждый файл, который его использует.
Исправление 4: начни путь с правильного места
Заголовок раздела «Исправление 4: начни путь с правильного места»Выбирай это, когда импорт стоит внутри модуля, а нужный элемент живёт в другом модуле твоего же крейта. Здесь receipt лежит внутри shop и хочет получить shop::store_name:
mod shop { pub fn store_name() -> &'static str { "Ferris Fruits" }
pub mod receipt { use store_name; // ❌ looks in the wrong place
pub fn header() -> String { format!("== {} ==", store_name()) } }}error[E0432]: unresolved import `store_name` --> src/main.rs:7:13 |7 | use store_name; // ❌ looks in the wrong place | ^^^^^^^^^^ no external crate `store_name`Комментарий говорит, что импорт ищет не там, а rustc сообщает, что внешнего крейта 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; |
Все три в одной программе:
mod shop { pub fn store_name() -> &'static str { "Ferris Fruits" }
pub mod prices { pub fn price_of(item: &str) -> u32 { if item == "яблоко" { 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("яблоко");}Вывод:
== Ferris Fruits ==яблоко: 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. Исправление: загляни в документацию крейта на docs.rs для той версии, что указана в твоём Cargo.toml. Здесь новое имя — rand::rng(). Подробнее в уроке Случайные числа.
Пакет, в котором есть и main.rs, и lib.rs. Это два отдельных крейта. Внутри main.rs crate:: означает бинарный крейт, поэтому use crate::inventory::count_items; падает с could not find `inventory` in the crate root, хотя в lib.rs есть pub mod inventory;. Исправление: используй имя пакета, use shop_app::inventory::count_items; (дефисы заменяются подчёркиваниями).
Элемент существует, но он приватный. Это другая ошибка, E0603, а не E0432:
error[E0603]: function `count_items` is private --> src/main.rs:7:16 |7 | use inventory::count_items; | ^^^^^^^^^^^ private functionКомпилятор говорит, что функция count_items приватная. Исправление: добавь pub перед fn (и перед каждым mod на пути к ней, ведь приватный модуль даёт module `prices` is private). Подробнее в уроке Модули.
Связанные ошибки
Заголовок раздела «Связанные ошибки»- E0433: не удаётся разрешить путь внутри твоего кода (например,
HashMap::new()илиrand::rng()). Причины те же, но не в строкеuse. - E0425: не найдено значение или функция; часто исправляется той же строкой
use. - E0603: импорт нашёлся, но он приватный. Добавь
pub. - E0463:
can't find crate, её ты получишь отextern crate rand;, когда крейта нет вCargo.toml. - Все ошибки компилятора: полный список страниц с ошибками.
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
1. Ты скопировал use serde::Serialize; в новый проект и получил E0432: крейт serde не найден или не подключён. Как это исправить?
2. Ты создал src/billing.rs, но use billing::total; в main.rs не работает. Чего не хватает?
3. Внутри mod shop { mod receipt { ... } }: как receipt импортирует функцию, объявленную прямо в shop?
Результат: 0 / 3
Что почитать
Заголовок раздела «Что почитать»- E0432 — список кодов ошибок Rust (на английском): официальное объяснение, в том числе о том, как изменились пути в Rust 2018.
- Введение путей в область видимости с помощью ключевого слова use — книга «Язык программирования Rust» (перевод на русский): как работает
use, с внешними пакетами и вложенными путями. - Пути для ссылки на элемент в дереве модулей — книга «Язык программирования Rust» (перевод на русский): абсолютные пути через
crate::, относительные пути иsuper. - Separating Modules into Different Files — The Rust Book (на английском): куда писать
mod, когда модуль лежит в отдельном файле. cargo add— The Cargo Book (на английском): все опции для добавления зависимостей, включая features.