Ir al contenido

Error E0433 de Rust: failed to resolve, use of undeclared type

E0433 significa que escribiste una ruta como HashMap::new() o rand::rng(), y Rust no sabe qué es la primera parte. Casi siempre falta una sola línea: un use, una dependencia en Cargo.toml o una declaración mod. La buena noticia es que rustc suele imprimir esa línea exacta para que la copies. Esta página forma parte de la guía de errores del compilador.

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;
|

Este es el programa que lo produce:

fn main() {
let mut stock = HashMap::new();
stock.insert("manzanas", 12);
println!("{:?}", stock.get("manzanas"));
}

Las versiones antiguas de Rust muestran este mismo error como “failed to resolve: use of undeclared type HashMap” (no se pudo resolver: uso de un tipo no declarado). Según lo que falte, la etiqueta también puede decir use of unresolved module or unlinked crate (para un crate o un módulo) en lugar de use of undeclared type. Todos son E0433, y todos se arreglan igual.

Los ^^^^^^^ señalan HashMap, la parte antes de los ::. Para llamar a HashMap::new(), Rust primero tiene que encontrar algo llamado HashMap. Miró todo lo que es visible desde la línea 2 y no encontró nada con ese nombre, así que ni siquiera puede empezar a buscar new.

La línea help: es la parte importante. rustc buscó en la biblioteca estándar, encontró un struct llamado HashMap en std::collections y te muestra la línea use que lo haría visible (“consider importing this struct”, considera importar este struct). El 1 + significa “añade esto como línea 1”.

Es como pedirle a un bibliotecario “el capítulo 3 de ese libro” sin decirle qué libro. Sabe que hay un capítulo 3 en muchísimos libros, pero primero necesita el título.

Solo un pequeño grupo de nombres es visible automáticamente en todos los archivos de Rust. Se llama el prelude (preludio): Vec, String, Option, Some, None, Result, Ok, Err, Box y unos cuantos traits. Todo lo demás, incluidos HashMap, HashSet, fs y Ordering, hay que traerlo con use o escribirlo con su ruta completa.

Así el prelude se mantiene pequeño y se evitan choques de nombres. La biblioteca estándar tiene, por ejemplo, dos tipos Ordering distintos, y tu propio código puede tener también un Duration o un Result. Rust no va a adivinar cuál querías. Lo dices una vez al principio del archivo, y cualquiera que lo lea ve de dónde sale cada nombre.

Lo mismo vale para los crates y los módulos: un crate solo existe para tu código cuando aparece en Cargo.toml, y un módulo solo cuando tiene su línea mod. Mira Módulos y Cargo y crates.

Solución 1: Añade la línea use que sugiere rustc

Sección titulada «Solución 1: Añade la línea use que sugiere rustc»

Elige esta cuando la línea help: dice consider importing. Es, con diferencia, la solución más común. Copia la línea sugerida al principio del archivo:

use std::collections::HashMap;
fn main() {
let mut stock = HashMap::new();
stock.insert("manzanas", 12);
println!("{:?}", stock.get("manzanas"));
}

Salida:

Some(12)
▶ Pruébalo tú mismo

La otra opción es escribir la ruta completa donde lo usas, std::collections::HashMap::new(). También funciona, pero tendrías que repetirla en todas partes, así que lo normal es una línea use. Tienes más sobre este tipo en HashMaps.

Si rustc te ofrece varias importaciones (consider importing one of these, considera importar uno de estos), léelas antes de elegir. Son tipos distintos que comparten nombre, y solo uno de ellos es el que querías.

Solución 2: Corrige el nombre del tipo o declara el tipo

Sección titulada «Solución 2: Corrige el nombre del tipo o declara el tipo»

Elige esta cuando el nombre es de un tipo tuyo. Si no hay ningún help:, el tipo todavía no existe; si hay una errata, rustc te señala el nombre parecido:

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();
| +

La ayuda dice que existe un struct con un nombre parecido, y el + bajo la línea muestra la letra que falta. Corrige el nombre:

struct Inventory {
items: Vec<String>,
}
impl Inventory {
fn new() -> Self {
Inventory { items: Vec::new() }
}
}
fn main() {
let stock = Inventory::new();
println!("{} artículos", stock.items.len());
}

Salida:

0 artículos
▶ Pruébalo tú mismo

Si Order::new() da E0433 sin ninguna sugerencia, es que todavía no has escrito struct Order (o que está en un archivo que no has declarado con mod). Revisa también las mayúsculas: inventory::new() e Inventory::new() son nombres distintos.

Solución 3: Nombra el módulo donde vive el tipo

Sección titulada «Solución 3: Nombra el módulo donde vive el tipo»

Elige esta cuando el tipo o el enum está definido dentro de un módulo y lo usas desde fuera. Aquí el enum está en mod traffic, pero main escribe 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;
|

rustc encontró el enum Light dentro de traffic y te propone importarlo. Importa el enum (o escribe traffic::Light::Green). Fíjate en que importas el enum, y aun así sigues escribiendo Light::Green para cada variante:

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:?}: ¿se puede pasar? {}", can_go(&now));
}

Salida:

Green: ¿se puede pasar? true
▶ Pruébalo tú mismo

La ruta de una variante tiene exactamente dos partes: Enum::Variant. Si escribes una parte de más, como Light::Red::Green, obtienes E0433 con cannot find module `Red` in `Light` y la etiqueta `Red` is a variant, not a module (Red es una variante, no un módulo). Mira Enums.

Solución 4: Añade el crate o declara el módulo

Sección titulada «Solución 4: Añade el crate o declara el módulo»

Elige esta cuando la etiqueta dice use of unresolved module or unlinked crate. La primera parte de la ruta es un crate o un módulo que Rust no conoce:

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 no encuentra ningún módulo ni crate llamado rand, y te sugiere añadirlo con cargo add. Para un crate de crates.io, ejecuta cargo add rand en la carpeta de tu proyecto. Para un módulo de la biblioteca estándar como fs, rustc te sugiere use std::fs;. Y para un archivo tuyo, por ejemplo src/inventory.rs, la ayuda dice to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module (para usar ese archivo, declara el módulo con mod inventory):

src/
├── main.rs inventory::count_items() ← necesita `mod inventory;` al principio
└── inventory.rs pub fn count_items() -> u32 { 42 }

Este es el mismo programa en un solo archivo, con el módulo escrito en línea para que funcione en el Playground:

mod inventory {
pub fn count_items() -> u32 {
42
}
}
fn main() {
println!("Artículos en inventario: {}", inventory::count_items());
}

Salida:

Artículos en inventario: 42
▶ Pruébalo tú mismo

Con un archivo separado, lo único que cambia es que mod inventory { ... } pasa a ser mod inventory; y el cuerpo se muda a src/inventory.rs.

Puede que veas extern crate rand; en código antiguo. Desde la edición 2018 no hace falta: en cuanto un crate está en Cargo.toml, puedes usarlo directamente. Añadir extern crate no arregla E0433. Sin la dependencia, solo cambia el error por E0463, can't find crate for rand (no se encuentra el crate rand). La solución de verdad es cargo add.

Comparar con cmp. Un match a.cmp(&b) con ramas Ordering::Less da E0433, y rustc sugiere dos importaciones: use std::cmp::Ordering; y use std::sync::atomic::Ordering;. La que quieres es std::cmp::Ordering; la atómica es para hilos. Mira Match.

Pruebas en un bloque mod tests. Un módulo de pruebas es un módulo hijo, así que no ve tus tipos si no los importas. Inventory::new() dentro de mod tests da E0433 con help: consider importing this struct y use crate::Inventory;. Solución: pon use super::*; al principio del módulo de pruebas. Mira Testing.

Código pegado de la documentación o de un blog. Los ejemplos a menudo se saltan sus líneas use. fs::read_to_string(...) falla con cannot find module or crate `fs` in this scope y la ayuda use std::fs;. Solución: añade la importación que te muestra rustc, o busca la ruta del elemento en su página de documentación.

  • E0432: el mismo tipo de problema en una línea use, unresolved import (importación no resuelta).
  • E0425: no se encuentra un valor o una función (sin :: de por medio), como una variable mal escrita. El rustc actual también usa E0425 cuando falta un tipo en una posición de tipo, como let m: HashMap<&str, u32>; las versiones antiguas lo llaman E0412. La misma línea use lo arregla.
  • E0599: el tipo se encontró, pero el método o la variante que va después de :: no existe, como Light::Blue.
  • E0463: can't find crate, por un extern crate sin la dependencia.
  • Todos los errores del compilador: la lista completa de páginas de errores.

Comprueba lo aprendido

1. ¿Por qué HashSet::new() da E0433 cuando Vec::new() funciona sin ninguna importación?

2. rustc sugiere use std::cmp::Ordering; y también use std::sync::atomic::Ordering; para tu match a.cmp(&b). ¿Cuál eliges?

3. rand::rng() da E0433 con la etiqueta 'use of unresolved module or unlinked crate'. ¿Qué lo arregla?

Puntuación: 0 / 3