Error E0432 de Rust: unresolved import (importación no resuelta)
E0432 significa que una de tus líneas use apunta a algo que Rust no encuentra. Quizá el crate todavía no está en Cargo.toml, quizá hay una pequeña errata en la ruta, o quizá el archivo existe pero Rust no sabe que es un módulo. Asusta un poco, pero casi siempre se arregla con una sola línea, y normalmente el compilador te dice cuál. Esta página forma parte de la guía de errores del compilador.
El mensaje de error
Sección titulada «El mensaje de error»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`Este es el programa que lo produce, en un proyecto recién creado con cargo new y sin nada bajo [dependencies]:
use rand::random_range;
fn main() { let roll = random_range(1..=6); println!("Sacaste un {roll}");}El texto bajo los ^^^^ cambia según la causa. Todos estos casos son E0432, y cada uno te lleva a una solución distinta de las de abajo:
| Lo que dice la etiqueta | Lo que suele haber fallado | Solución |
|---|---|---|
use of unresolved module or unlinked crate |
falta el crate en Cargo.toml, o un archivo no tiene su línea mod |
Solución 1 o 3 |
could not find `collection` in `std` |
una errata en medio de la ruta | Solución 2 |
no `Hashmap` in `collections` |
una errata (o mayúsculas mal puestas) en el último nombre | Solución 2 |
could not find `inventory` in the crate root |
una ruta crate:: hacia un módulo que no está declarado |
Solución 3 |
no external crate |
la ruta empieza en el módulo equivocado | Solución 4 |
Qué significa
Sección titulada «Qué significa»Una línea use es un atajo. use rand::random_range; dice “a partir de ahora, random_range significa lo que hay en rand::random_range”. Antes de crear ese atajo, Rust tiene que recorrer la ruta pieza a pieza: primero encontrar rand y después encontrar random_range dentro.
Los ^^^^ señalan la primera pieza que falló. Aquí es rand, el primer segmento, así que Rust ni siquiera llegó a buscar random_range. La línea help: adivina el motivo: rand es un crate de crates.io, y este proyecto no lo ha añadido. “Unresolved import” significa justo eso: una importación que Rust no pudo resolver.
Es como darle a un taxista la dirección “Calle del Puerto 12, Springfeld”. Si el nombre del pueblo está mal, el taxista no puede ni empezar a buscar la calle.
Por qué Rust hace esto
Sección titulada «Por qué Rust hace esto»Rust resuelve todas las rutas al compilar, no cuando el programa se ejecuta. No se carga nada “por si acaso”. Tu código solo puede ver tres tipos de cosas: los crates que aparecen en Cargo.toml (además de std), los módulos que declaraste con mod y los elementos que hay dentro de ellos. Si una línea use nombra algo fuera de ese conjunto, Rust se detiene en el acto en lugar de adivinar.
Y eso es bueno. Una importación mal escrita en Python o JavaScript a menudo solo falla cuando esa línea por fin se ejecuta, quizá en producción. En Rust el programa ni siquiera compila. Además, así un crate que nunca añadiste no puede colarse en tu programa.
Desde la edición 2018, una ruta de use empieza en uno de estos sitios: el nombre de un crate (std, rand), crate (la raíz de tu propio crate), self (el módulo actual), super (el módulo padre) o un módulo declarado en el módulo actual. La lección de Módulos lo explica en detalle, y Cargo y crates explica las dependencias.
Cómo solucionarlo
Sección titulada «Cómo solucionarlo»Solución 1: Añade el crate con cargo add
Sección titulada «Solución 1: Añade el crate con cargo add»Elige esta cuando el primer segmento es un crate de crates.io, como rand, serde o regex, y la línea help: menciona cargo add. Es la causa más común, sobre todo cuando copias código de un blog. Ejecuta esto en la carpeta que contiene Cargo.toml:
cargo add randCargo busca la versión más reciente y añade una línea a Cargo.toml por ti:
[dependencies]rand = "0.10.3"Ahora el mismo código compila. Esta versión imprime una comprobación en lugar de la tirada en sí, para que la salida sea siempre la misma:
use rand::random_range;
fn main() { let roll = random_range(1..=6); println!("La tirada está entre 1 y 6: {}", (1..=6).contains(&roll));}Salida:
La tirada está entre 1 y 6: trueAquí hay dos cosas que suelen confundir. Primero, los nombres de crate con guion se escriben con guion bajo en el código: haces cargo add tracing-subscriber, pero escribes use tracing_subscriber::.... Segundo, si el crate es una dependencia de tu workspace, igualmente tiene que aparecer en el Cargo.toml del paquete que lo usa.
Solución 2: Corrige cómo está escrita la ruta
Sección titulada «Solución 2: Corrige cómo está escrita la ruta»Elige esta cuando la etiqueta dice could not find `X` in `Y` (no se encuentra X en Y) o no `X` in `Y` (no hay X en Y). Algo en medio o al final de la ruta está mal escrito. Un clásico:
error[E0432]: unresolved import `std::collection` --> src/main.rs:1:10 |1 | use std::collection::HashMap; | ^^^^^^^^^^ could not find `collection` in `std`El módulo se llama collections, con s. Los nombres también distinguen mayúsculas y minúsculas: use std::collections::Hashmap; falla con no `Hashmap` in `collections`, y rustc añade help: a similar name exists in the module (existe un nombre parecido en el módulo) con la forma correcta. La importación corregida:
use std::collections::HashMap;
fn main() { let mut stock: HashMap<&str, u32> = HashMap::new(); stock.insert("manzanas", 12); println!("{:?}", stock.get("manzanas"));}Salida:
Some(12)Si no estás seguro de la ruta exacta, búscala en la documentación de la biblioteca estándar (en inglés). La página de cada elemento muestra su ruta completa arriba del todo. En HashMaps tienes más sobre este tipo.
Solución 3: Declara el módulo con mod
Sección titulada «Solución 3: Declara el módulo con mod»Elige esta cuando creaste un archivo nuevo, por ejemplo src/inventory.rs, y use inventory::... no lo encuentra. En Rust, un archivo no es un módulo hasta que un archivo padre lo declara. Tu proyecto se ve así:
src/├── main.rs use inventory::count_items; ← falta `mod inventory;`└── inventory.rs pub fn count_items() -> u32 { 42 }Y rustc te dice exactamente qué falta:
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; |La ayuda dice: “para usar el archivo src/inventory.rs, declara el módulo con mod inventory en este archivo”. Añade mod inventory; al principio de src/main.rs (o de src/lib.rs, si el módulo pertenece a tu biblioteca). Escribir use crate::inventory::count_items; en su lugar no ayuda: falla con could not find `inventory` in the crate root (no se encuentra inventory en la raíz del crate), porque el módulo sigue sin estar declarado.
En el Playground todo vive en un solo archivo, así que aquí el módulo se escribe en línea con mod inventory { ... }. Funciona exactamente igual que el archivo separado:
mod inventory { pub fn count_items() -> u32 { 42 }}
use inventory::count_items;
fn main() { println!("Artículos en inventario: {}", count_items());}Salida:
Artículos en inventario: 42Declara cada módulo una sola vez, en su padre. Los demás archivos llegan a él con use crate::inventory::.... No añadas mod inventory; en cada archivo que lo use.
Solución 4: Empieza la ruta desde el sitio correcto
Sección titulada «Solución 4: Empieza la ruta desde el sitio correcto»Elige esta cuando la importación está dentro de un módulo y el elemento vive en otro módulo de tu propio crate. Aquí receipt está dentro de shop y quiere shop::store_name:
mod shop { pub fn store_name() -> &'static str { "Ferris Fruits" }
pub mod receipt { use store_name; // ❌ busca en el sitio equivocado
pub fn header() -> String { format!("== {} ==", store_name()) } }}error[E0432]: unresolved import `store_name` --> src/main.rs:7:13 |7 | use store_name; // ❌ busca en el sitio equivocado | ^^^^^^^^^^ no external crate `store_name`Un nombre suelto al principio de una ruta use significa “un crate, o algo declarado aquí mismo, en este módulo”. store_name no es ninguna de las dos cosas, así que Rust buscó un crate con ese nombre y no lo encontró (“no external crate”, no hay ningún crate externo). Dile por dónde empezar:
| Prefijo | Empieza desde | Ejemplo |
|---|---|---|
crate:: |
la raíz de tu crate (main.rs o lib.rs) |
use crate::shop::prices::price_of; |
super:: |
el módulo padre | use super::store_name; |
self:: |
el módulo actual | use self::lines::line; |
Los tres en un mismo programa:
mod shop { pub fn store_name() -> &'static str { "Ferris Fruits" }
pub mod prices { pub fn price_of(item: &str) -> u32 { if item == "manzana" { 3 } else { 5 } } }
pub mod receipt { use super::store_name; // módulo padre: shop use crate::shop::prices::price_of; // desde la raíz del crate use self::layout::line; // hijo de este módulo
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("manzana");}Salida:
== Ferris Fruits ==manzana: 3use layout::line; también funcionaría aquí, porque layout está declarado en el módulo actual; self:: solo lo hace explícito. Si tienes dudas, crate:: con la ruta completa funciona desde cualquier parte de tu crate, y rustc a menudo lo sugiere: help: a similar path exists (existe una ruta parecida) seguido de la versión con crate::.
Dónde suele aparecer
Sección titulada «Dónde suele aparecer»Código escrito para una versión antigua de un crate. Muchos tutoriales usan rand 0.8. Con rand 0.10 obtienes:
error[E0432]: unresolved import `rand::thread_rng` --> src/main.rs:1:5 |1 | use rand::thread_rng; | ^^^^^^^^^^^^^^^^ no `thread_rng` in the rootrustc encontró el crate rand, pero en su raíz ya no hay nada llamado thread_rng. Solución: consulta la documentación del crate en docs.rs para la versión que tienes en Cargo.toml. Aquí el nombre nuevo es rand::rng(). Mira Números aleatorios.
Un paquete con main.rs y lib.rs a la vez. Son dos crates distintos. Dentro de main.rs, crate:: significa el binario, así que use crate::inventory::count_items; falla con could not find `inventory` in the crate root aunque lib.rs tenga pub mod inventory;. Solución: usa el nombre del paquete, use shop_app::inventory::count_items; (con los guiones convertidos en guiones bajos).
El elemento existe, pero es privado. Ese es otro error, E0603, no E0432:
error[E0603]: function `count_items` is private --> src/main.rs:7:16 |7 | use inventory::count_items; | ^^^^^^^^^^^ private functionAquí Rust sí encontró count_items, pero la función es privada (“private function”). Solución: añade pub delante del fn (y delante de cada mod del camino, porque un módulo privado da module `prices` is private). Mira Módulos.
Errores relacionados
Sección titulada «Errores relacionados»- E0433: una ruta dentro de tu código (como
HashMap::new()orand::rng()) no se puede resolver. Las mismas causas, pero no en una líneause. - E0425: no se encuentra un valor o una función; a menudo lo arregla la misma línea
use. - E0603: la importación se encontró, pero es privada. Añade
pub. - E0463:
can't find crate(no se encuentra el crate), que aparece conextern crate rand;cuando el crate no está enCargo.toml. - Todos los errores del compilador: la lista completa de páginas de errores.
Comprueba lo que aprendiste
Sección titulada «Comprueba lo que aprendiste»Comprueba lo aprendido
1. Copiaste use serde::Serialize; en un proyecto nuevo y obtienes un E0432 que dice que el crate serde no está resuelto o enlazado. ¿Cuál es la solución?
2. Creaste src/billing.rs, pero use billing::total; en main.rs falla. ¿Qué falta?
3. Dentro de mod shop { mod receipt { ... } }, ¿cómo importa receipt una función definida directamente en shop?
Puntuación: 0 / 3
Para leer más
Sección titulada «Para leer más»- E0432 — Rust error codes index (en inglés): la explicación oficial, incluido cómo cambiaron las rutas en Rust 2018.
- Bringing Paths into Scope with the
useKeyword — The Rust Book (en inglés): cómo funcionause, con paquetes externos y rutas anidadas. También existe una traducción al español de la comunidad del libro. - Paths for Referring to an Item in the Module Tree — The Rust Book (en inglés): rutas absolutas con
crate::, rutas relativas ysuper. - Separating Modules into Different Files — The Rust Book (en inglés): dónde va
modcuando un módulo vive en su propio archivo. cargo add— The Cargo Book (en inglés): todas las opciones para añadir dependencias, incluidas las features.