Error E0412 de Rust: cannot find type in this scope (tipo no encontrado)
E0412 significa que escribiste un nombre de tipo que Rust no puede ver desde ese punto, por ejemplo en la firma de una función como fn print_invoice(inv: &Invoce). Es un error muy común y fácil de arreglar: un error al escribir, una línea use que falta, o un genérico <T> que olvidaste declarar. Hay algo que al principio puede confundirte: desde Rust 1.93, el compilador muestra este error como E0425, con el mismo mensaje, cannot find type (no se encuentra el tipo). Esta página trata los dos códigos, y forma parte de la guía de errores del compilador.
El mensaje de error
Sección titulada «El mensaje de error»Esto es lo que muestran Rust 1.93 y las versiones más nuevas (el compilador actual es el 1.97):
error[E0425]: cannot find type `Invoce` in this scope --> src/main.rs:2:24 |1 | struct Invoice { total: u32 } | -------------- similarly named struct `Invoice` defined here2 | fn print_invoice(inv: &Invoce) { // ❌ typo: Invoce | ^^^^^^ |help: a struct with a similar name exists |2 | fn print_invoice(inv: &Invoice) { // ❌ typo: Invoce | +Y este es el mismo programa con Rust 1.92 o anterior, la versión con la que se escribieron la mayoría de los artículos de blog y las respuestas de Stack Overflow:
error[E0412]: cannot find type `Invoce` in this scope --> src/main.rs:2:24 |1 | struct Invoice { total: u32 } | -------------- similarly named struct `Invoice` defined here2 | fn print_invoice(inv: &Invoce) { | ^^^^^^ help: a struct with a similar name exists: `Invoice`“Cannot find type Invoce in this scope” quiere decir “no se encuentra el tipo Invoce en este ámbito”. Los dos mensajes señalan dónde está definido el struct Invoice, de nombre parecido, y el help te avisa de que existe un struct con un nombre parecido.
Este es el programa que produce los dos:
struct Invoice { total: u32 }fn print_invoice(inv: &Invoce) { // ❌ typo: Invoce println!("{}", inv.total);}
fn main() { print_invoice(&Invoice { total: 120 });}La página oficial de E0412 (en inglés) ahora empieza con “this error code is no longer emitted by the compiler” (el compilador ya no emite este código de error). El problema no ha desaparecido, solo se ha mudado a E0425, que también cubre las variables y funciones que no se encuentran. Todo lo que verás abajo funciona igual con los dos códigos.
Qué significa
Sección titulada «Qué significa»Los ^^^^^^ señalan Invoce en la firma. Para comprobar esta función, Rust tiene que saber qué es un Invoce: cuánto ocupa y qué campos tiene. Miró todos los tipos visibles desde la línea 2 (tus propios structs y enums, tus líneas use y el preludio) y no encontró nada con ese nombre.
La línea help: te dice en qué situación estás:
- “a struct with a similar name exists” (existe un struct con un nombre parecido): un error al escribir. El
+te enseña la letra que falta. - “consider importing this struct” (prueba a importar este struct): el tipo existe en otro sitio, y necesitas una línea
use. - “you might be missing a type parameter” (puede que te falte un parámetro de tipo): usaste un genérico
Tsin declarar<T>. - ninguna ayuda: el tipo todavía no existe. No lo has escrito, o está en un archivo que Rust no conoce.
Es como una receta que dice “añade 200 g de Invoce”. Quien cocina sabe qué son la harina y el azúcar, pero no qué es “Invoce”, así que se detiene antes de empezar.
Por qué Rust hace esto
Sección titulada «Por qué Rust hace esto»Rust comprueba la firma de cada función antes de que el programa se ejecute. Cada parámetro y cada tipo de retorno tiene que nombrar un tipo real y conocido, porque Rust lo usa para decidir cuánta memoria necesita el valor y qué métodos y campos tiene. Un nombre que no encuentra no es algo que esté dispuesto a adivinar.
Solo un pequeño grupo de nombres de tipos es visible en todas partes sin un use: el preludio (prelude), con String, Vec, Option, Result, Box y algunos más. Todo lo demás necesita tu propia definición, una línea use o una ruta completa como std::num::ParseIntError. Mira Módulos para ver cómo funcionan las rutas y use.
¿Por qué cambió el código? Desde Rust 1.93, rustc informa de un tipo que no se encuentra con E0425, el mismo código que ya usaba para una variable o una función que no se encuentra. El mensaje sigue diciendo type, así que siempre puedes saber qué clase de nombre falta.
Cómo solucionarlo
Sección titulada «Cómo solucionarlo»Solución 1: Corrige el nombre, o define el tipo
Sección titulada «Solución 1: Corrige el nombre, o define el tipo»Elige esta cuando rustc diga que existe un nombre parecido, o cuando no dé ninguna ayuda. Los nombres de tipos distinguen entre mayúsculas y minúsculas: invoice, Invoce e Invoice son tres nombres distintos. Si no hay ningún nombre parecido, escribe primero el struct o el enum:
struct Invoice { total: u32,}
fn print_invoice(inv: &Invoice) { println!("Total de la factura: {} EUR", inv.total);}
fn main() { print_invoice(&Invoice { total: 120 });}Salida:
Total de la factura: 120 EURSolución 2: Añade la línea use que sugiere rustc
Sección titulada «Solución 2: Añade la línea use que sugiere rustc»Elige esta cuando el help diga consider importing this struct (o enum, o alias de tipo). Los tipos de la biblioteca estándar que no están en el preludio, como HashMap, ParseIntError u Ordering, necesitan una línea use. Aquí una función devuelve un error de conversión:
error[E0425]: cannot find type `ParseIntError` in this scope --> src/main.rs:1:40 |1 | fn parse_age(text: &str) -> Result<u8, ParseIntError> { | ^^^^^^^^^^^^^ not found in this scope |help: consider importing this struct |1 + use std::num::ParseIntError; |La etiqueta not found in this scope significa “no se encuentra en este ámbito”, y el help te da la línea exacta que hay que añadir. Cópiala al principio del archivo:
use std::num::ParseIntError;
fn parse_age(text: &str) -> Result<u8, ParseIntError> { text.trim().parse()}
fn main() { println!("{:?}", parse_age(" 42 ")); println!("{:?}", parse_age("cuarenta").is_err());}Salida:
Ok(42)trueSi escribiste HashMap::new() (una ruta con ::) en lugar de un tipo en una firma, el error es E0433, y lo arregla la misma línea use. Si rustc sugiere varios imports, léelos antes de elegir: son tipos distintos que comparten nombre.
Solución 3: Declara el parámetro de tipo genérico
Sección titulada «Solución 3: Declara el parámetro de tipo genérico»Elige esta cuando el help diga you might be missing a type parameter. En Rust, T no es una palabra especial. Es un nombre que inventas tú, y tienes que anunciarlo entre < > después del nombre de la función. Sin <T>, Rust busca un tipo real llamado T:
error[E0425]: cannot find type `T` in this scope --> src/main.rs:1:21 |1 | fn largest(items: &[T]) -> &T { | ^ not found in this scope |help: you might be missing a type parameter |1 | fn largest<T>(items: &[T]) -> &T { | +++rustc no encuentra el tipo T y te sugiere añadir <T> después de largest. Recibes el mismo error una vez por cada sitio donde aparece T. Añade <T>, más los traits que necesite la función. Para comparar elementos con >, T tiene que implementar PartialOrd:
fn largest<T: PartialOrd>(items: &[T]) -> &T { let mut best = &items[0]; for item in items { if item > best { best = item; } } best}
fn main() { println!("{}", largest(&[34, 50, 25, 100, 65])); println!("{}", largest(&['y', 'm', 'a', 'q']));}Salida:
100yCon los structs pasa lo mismo: struct Wrapper { items: Vec<Item> } falla a menos que escribas struct Wrapper<Item> o definas un tipo Item real. Si quitas : PartialOrd, obtienes en su lugar E0369 en el >. Mira Una función genérica.
Solución 4: Importa un tipo desde otro módulo
Sección titulada «Solución 4: Importa un tipo desde otro módulo»Elige esta cuando el tipo es tuyo pero vive en otro módulo. Una sorpresa habitual: un módulo dentro de tu archivo tampoco puede ver los tipos de la parte de arriba del archivo. Cada módulo tiene su propio ámbito:
error[E0425]: cannot find type `Order` in this scope --> src/main.rs:7:26 |7 | pub fn print(order: &Order) -> String { | ^^^^^ not found in this scope |help: consider importing this struct |7 + use crate::Order; |El 7 + significa “añade esta línea dentro del módulo, en la línea 7”. crate::Order es la ruta desde la raíz de tu crate; super::Order (“desde el módulo padre”) también funciona:
struct Order { id: u32, total: u32,}
mod receipts { use crate::Order;
pub fn print(order: &Order) -> String { format!("Pedido #{}: {} EUR", order.id, order.total) }}
fn main() { let order = Order { id: 7, total: 42 }; println!("{}", receipts::print(&order));}Salida:
Pedido #7: 42 EUREn la otra dirección funciona igual: un tipo definido en mod shop necesita pub struct Product y use crate::shop::Product; (o la ruta completa shop::Product) para que main pueda nombrarlo. Donde más lo verás es en mod tests, donde un use super::*; al principio importa todo lo del módulo padre.
Dónde lo verás normalmente
Sección titulada «Dónde lo verás normalmente»Un tipo de un archivo que no has declarado. fn save(user: models::User) con un archivo src/models.rs pero sin la línea mod models; no da E0412 ni E0425, sino E0433: cannot find module or crate `models` in this scope (no se encuentra el módulo o crate models en este ámbito). Solución: añade mod models; al principio de main.rs, y haz que el struct sea pub.
Self fuera de un impl. fn new_counter() -> Self fuera de cualquier bloque da su propio código, E0411: cannot find type `Self` in this scope, con la etiqueta `Self` is only available in impls, traits, and type definitions (Self solo está disponible en impls, traits y definiciones de tipos). Solución: mueve la función a impl Counter { ... }, o escribe Counter en lugar de Self.
Un trait en lugar de un tipo. impl Display for Point sin importar Display da E0405, cannot find trait `Display` in this scope (no se encuentra el trait Display en este ámbito), con help: consider importing this trait y use std::fmt::Display;. La misma idea y la misma solución: añade la línea use. Mira Traits.
Errores relacionados
Sección titulada «Errores relacionados»- E0425: no se encuentra un valor, una función y, desde Rust 1.93, también un tipo. Es el código que verás de verdad hoy.
- E0433: no se encuentra la primera parte de una ruta como
HashMap::new()omodels::User. - E0432: unresolved import (import sin resolver), cuando la propia línea
useno apunta a nada. - E0603: el tipo se encontró, pero no es
pub. - E0405 (no se encuentra el trait) y E0411 (
Selffuera de un impl): los primos cercanos que viste arriba. - 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. Seguiste un tutorial que muestra error[E0412]: cannot find type, pero tu compilador muestra error[E0425]: cannot find type. ¿Por qué?
2. fn first(items: &[T]) -> &T da cannot find type T. ¿Cómo lo arreglas?
3. Una función dentro de mod billing usa Order, un struct definido al principio de main.rs. ¿Qué línea, dentro del módulo, lo arregla?
Puntuación: 0 / 3
Para leer más
Sección titulada «Para leer más»- E0412 — Rust error codes index (en inglés): la página oficial, con la nota de que este código ya no se emite, y los ejemplos clásicos.
- E0425 — Rust error codes index (en inglés): el código que usa el compilador actual para este error.
- Generic Data Types — El libro de Rust (en inglés): cómo declarar
<T>, con la misma funciónlargestde la Solución 3. También existe una traducción al español de la comunidad del libro. - Bringing Paths into Scope with the
useKeyword — El libro de Rust (en inglés):use,crate::ysuper::para tipos de otros módulos. std::prelude— documentación de la biblioteca estándar (en inglés): la lista de nombres que puedes usar sin importarlos.