Ir al contenido

Error E0405 de Rust: cannot find trait in this scope (trait no encontrado)

E0405 significa que nombraste un trait que Rust no ve desde ese sitio. El caso clásico: escribes impl Display for Point para que tu struct se pueda imprimir, pero nunca importaste Display. Una errata en el nombre del trait, o un trait que vive en otro módulo, dan el mismo error. Es uno de los errores más fáciles de arreglar, porque rustc normalmente te muestra la línea use exacta que necesitas. A diferencia de E0412 (“cannot find type”), que pasó a ser E0425 en Rust 1.93, este código no ha cambiado: rustc 1.97 sigue mostrando E0405 para los traits. Forma parte de la guía de errores del compilador.

error[E0405]: cannot find trait `Display` in this scope
--> src/main.rs:6:6
|
6 | impl Display for Point { // ❌ `Display` was never imported
| ^^^^^^^ not found in this scope
|
help: consider importing this trait
|
1 + use std::fmt::Display;
|

“Cannot find trait Display in this scope” quiere decir “no se encuentra el trait Display en este ámbito”, y el help te sugiere importarlo.

Este es el programa que lo produce:

struct Point {
x: i32,
y: i32,
}
impl Display for Point { // ❌ `Display` was never imported
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let p = Point { x: 3, y: 4 };
println!("{}", p);
}

El ^^^^^^^ señala Display en la línea 6, con la etiqueta “not found in this scope” (no encontrado en este ámbito). Rust miró todos los traits visibles desde ahí: los que definiste en este módulo, los que traen tus líneas use y el pequeño grupo del prelude (los nombres que vienen incluidos). Ninguno se llama Display.

El help: te dice dónde está: use std::fmt::Display;. El 1 + significa “añade esto como una nueva línea 1”, al principio del archivo.

¿Por qué falta Display si println! lo usa todo el rato? El prelude, la lista de nombres que cada archivo de Rust recibe gratis, incluye Clone, Iterator, From, Default y otros traits de todos los días, pero no Display, Error, Hash ni Write. Esos viven en sus módulos (std::fmt, std::error, std::hash, std::io), y los importas cuando los implementas.

Es como una receta que dice “usa la sartén Display”. El cocinero conoce las sartenes que están en el fuego, pero esta está en un armario, y la receta nunca dijo en cuál.

Rust nunca busca un nombre en toda la biblioteca estándar, ni en todo tu proyecto. Solo mira lo que está en el ámbito: tus propios elementos, tus líneas use y el prelude. Así los nombres son predecibles. Solo en std hay varios traits que se llaman Write y Error, y un crate que añadas más adelante podría traer más. Si Rust eligiera uno por ti, añadir una dependencia podría cambiar sin avisar lo que significa tu código.

Así que tú dices qué trait quieres, una vez, al principio del archivo. La línea del help hace la búsqueda por ti y te sugiere el trait que encontró. Mira use: acortar rutas largas para ver cómo funciona use, y Traits comunes para Display.

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 el help dice consider importing this trait (considera importar este trait), que es casi siempre. Copia la línea al principio del archivo:

use std::fmt::Display;
struct Point {
x: i32,
y: i32,
}
impl Display for Point {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let p = Point { x: 3, y: 4 };
println!("{}", p);
println!("Ferris está en {}", Point { x: -1, y: 7 });
}

Salida:

(3, 4)
Ferris está en (-1, 7)
▶ Pruébalo tú mismo

Si rustc sugiere varios imports, léelos antes de elegir. Son traits distintos que comparten nombre por casualidad, como std::fmt::Write y std::io::Write.

Solución 2: Importa el módulo y escribe fmt::Display

Sección titulada «Solución 2: Importa el módulo y escribe fmt::Display»

Elige esta cuando estás implementando Display, porque de todas formas necesitas Formatter y Result del mismo módulo. Importa std::fmt una vez y escribe fmt:: delante de los tres. Es el estilo que más verás en código Rust real:

use std::fmt;
struct Point {
x: i32,
y: i32,
}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let p = Point { x: 3, y: 4 };
let label = p.to_string();
println!("{} tiene {} caracteres", label, label.len());
}

Salida:

(3, 4) tiene 6 caracteres
▶ Pruébalo tú mismo

Implementar Display también te da .to_string() gratis. Puedes saltarte el use del todo y escribir impl std::fmt::Display for Point; está bien para un caso suelto.

Solución 3: Corrige cómo se escribe el nombre del trait

Sección titulada «Solución 3: Corrige cómo se escribe el nombre del trait»

Elige esta cuando rustc dice a trait with a similar name exists (existe un trait con un nombre parecido). Los nombres de los traits distinguen mayúsculas y minúsculas, así que shape, Shap y Shape son tres nombres distintos:

error[E0405]: cannot find trait `Shap` in this scope
--> src/main.rs:9:6
|
1 | trait Shape {
| ----------- similarly named trait `Shape` defined here
...
9 | impl Shap for Square { // ❌ typo: Shap
| ^^^^
|
help: a trait with a similar name exists
|
9 | impl Shape for Square { // ❌ typo: Shap
| +

La etiqueta de la línea 1 señala el trait Shape de nombre parecido. El programa con el error:

trait Shape {
fn area(&self) -> f64;
}
struct Square {
side: f64,
}
impl Shap for Square { // ❌ typo: Shap
fn area(&self) -> f64 {
self.side * self.side
}
}
fn main() {
let s = Square { side: 3.0 };
println!("{}", s.area());
}

El + debajo de la línea 9 muestra la letra que falta. Añádela:

trait Shape {
fn area(&self) -> f64;
}
struct Square {
side: f64,
}
impl Shape for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn main() {
let s = Square { side: 3.0 };
println!("{}", s.area());
}

Salida:

9
▶ Pruébalo tú mismo

Si no hay ningún nombre parecido ni ninguna sugerencia de import, el trait todavía no existe. Defínelo primero con trait Shape { ... }. Mira Definir un trait.

Solución 4: Importa tu propio trait desde su módulo

Sección titulada «Solución 4: Importa tu propio trait desde su módulo»

Elige esta cuando el trait es tuyo pero vive en otro módulo. Cada módulo tiene su propio ámbito, así que un trait de mod shapes no se ve al principio de main.rs hasta que lo importas:

error[E0405]: cannot find trait `Shape` in this scope
--> src/main.rs:11:6
|
11 | impl Shape for Square { // ❌ `Shape` lives in `mod shapes`
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
1 + use crate::shapes::Shape;
|

El programa con el error:

mod shapes {
pub trait Shape {
fn area(&self) -> f64;
}
}
struct Square {
side: f64,
}
impl Shape for Square { // ❌ `Shape` lives in `mod shapes`
fn area(&self) -> f64 {
self.side * self.side
}
}
fn main() {
println!("{}", Square { side: 2.0 }.area());
}

Añade la línea use y comprueba que el trait es pub. Sin pub, el propio import falla con E0603, “trait is private” (el trait es privado):

mod shapes {
pub trait Shape {
fn area(&self) -> f64;
}
}
use crate::shapes::Shape;
struct Square {
side: f64,
}
impl Shape for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn main() {
println!("{}", Square { side: 2.0 }.area());
}

Salida:

4
▶ Pruébalo tú mismo

Lo mismo pasa con los traits de los crates: impl Serialize for User necesita antes use serde::Serialize;. Mira Todo es privado por defecto.

Box<dyn Error> en main o en una función auxiliar. fn run() -> Result<(), Box<dyn Error>> sin import da cannot find trait `Error` in this scope, con help: consider importing this trait y use std::error::Error;. Solución: añade esa línea, o escribe Box<dyn std::error::Error>. Mira Errores personalizados.

Trait bounds (restricciones de traits) en genéricos. fn print_all<T: Display>(items: &[T]) da el mismo E0405 para Display, señalando la restricción. Solución: use std::fmt::Display;. Mira Genéricos.

Debug da otro código. impl Debug for Point o T: Debug sin import no es E0405 sino E0404: expected trait, found derive macro `Debug` (se esperaba un trait, se encontró la macro derive Debug). El prelude tiene la macro #[derive(Debug)], pero no el trait Debug. Solución: use std::fmt::Debug; (rustc te lo sugiere), o simplemente #[derive(Debug)] si no necesitas un formato propio.

  • E0425: no se encuentra un valor, una función o (desde Rust 1.93) un tipo en este ámbito.
  • E0412: el código antiguo de “cannot find type”, que ahora se muestra como E0425.
  • E0433: no se encuentra la primera parte de una ruta, como fmt::Display sin use std::fmt;.
  • E0599: no se encuentra un método, a menudo porque el trait que lo aporta no está importado.
  • E0277: el trait sí se encontró, pero tu tipo no lo implementa.
  • E0404: un nombre que existe pero no es un trait (como la macro Debug), como viste arriba.
  • Todos los errores del compilador: la lista completa de páginas de errores.

Comprueba lo aprendido

1. Escribes impl Display for Invoice y obtienes E0405. ¿Qué falta?

2. ¿Cuál de estos traits puedes usar sin ninguna línea use?

3. Tu trait Shape está definido en mod shapes, y impl Shape for Square está en main.rs. ¿Qué necesitas?

Puntuación: 0 / 3