Ir al contenido

Errores del compilador de Rust explicados

¿El compilador de Rust te ha soltado un error en rojo y no sabes qué quiere de ti? Estás en el lugar indicado. Todas las personas que programan en Rust ven estos errores, a menudo varias veces al día. La buena noticia: solo hay unos pocos que vas a encontrarte una y otra vez, y en cuanto los conoces, dejan de dar miedo.

Cada página de abajo toma un código de error, muestra el mensaje real, lo explica con palabras sencillas y te da soluciones que puedes ejecutar en el navegador. El compilador escribe sus mensajes siempre en inglés, así que aquí los verás tal cual, con su explicación en español.

Error Lo que dice el compilador En palabras sencillas
E0382 borrow of moved value Entregaste un valor y luego intentaste usarlo otra vez
E0502 cannot borrow as mutable because it is also borrowed as immutable Estás cambiando algo mientras alguien todavía lo está leyendo
E0499 cannot borrow as mutable more than once at a time Dos partes del código quieren cambiar lo mismo a la vez
E0308 mismatched types Pasaste un tipo donde se esperaba otro
E0277 the trait bound is not satisfied Un tipo no sabe hacer algo que le pediste (imprimirse, compararse, sumarse…)
E0106 missing lifetime specifier Rust no sabe cuánto tiempo sigue siendo válida una referencia que devuelves
E0425 cannot find value in this scope Un nombre está mal escrito, o se usa fuera del bloque donde existe
E0599 no method named … found Ese tipo no tiene ese método, o no importaste su trait
E0384 cannot assign twice to immutable variable Cambiaste una variable que no se declaró con mut
E0596 cannot borrow as mutable, as it is not declared as mutable Intentaste cambiar algo a través de una variable o referencia que no es mut
E0597 borrowed value does not live long enough Una referencia se sigue usando cuando el valor al que apunta ya no existe
E0515 cannot return reference to local variable Devolviste una referencia a algo que se libera al terminar la función
E0373 closure may outlive the current function, but it borrows … Una closure (a menudo un hilo) toma prestada una variable local que puede desaparecer antes de que se ejecute
E0369 binary operation == cannot be applied to type … Tu tipo (todavía) no admite ==, <, + y compañía
E0432 unresolved import Una línea use apunta a un crate, módulo o elemento que no se encuentra
E0433 cannot find type … in this scope (antes: failed to resolve) Una ruta como HashMap::new() usa un nombre que no está importado o no existe
E0424 self value is a keyword only available in methods with a self parameter Usaste self en una función que no recibe self
E0061 this function takes N arguments but M arguments were supplied Pasaste argumentos de más o de menos (Rust no tiene argumentos opcionales)
E0594 cannot assign to p.hp, as p is not declared as mutable Cambiaste un campo o un valor detrás de & sin acceso mut
E0004 non-exhaustive patterns: X not covered Tu match no cubre todos los valores posibles
E0507 cannot move out of x which is behind a shared reference Intentaste quedarte con algo que solo tenías prestado
E0603 function x is private Usaste una función, un struct o un módulo que no es pub
E0716 temporary value dropped while borrowed Guardaste una referencia a un valor que se descarta al final de la línea
E0463 can’t find crate for x Un crate (o la biblioteca estándar para un target) no está instalado
E0368 binary assignment operation += cannot be applied to type … Tu tipo no admite +=, -= y compañía
E0057 this function takes N arguments but M were supplied (note: closure defined here) Llamaste a una closure con argumentos de más o de menos
E0282 type annotations needed Rust no puede deducir un tipo por sí solo, así que tienes que indicarlo tú
E0609 no field x on type T El nombre del campo está mal escrito, o el valor está envuelto (por ejemplo, en un Option)
E0593 closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments Una closure recibe argumentos separados donde se espera una tupla (o un número distinto de argumentos)
E0631 type mismatch in closure arguments El tipo de un parámetro de la closure no coincide con lo que recibe (a menudo i32 frente a &i32)
E0005 refutable pattern in local binding let Some(x) = … puede fallar, así que un let normal no lo acepta
E0615 attempted to take value of method len on type String Escribiste s.len en lugar de s.len()
E0610 {integer} is a primitive type and therefore doesn’t have fields Usaste .campo sobre un número, un bool o un char
E0560 struct User has no field named nmae Al crear un struct usaste un nombre de campo que ese struct no tiene
E0616 field balance of struct Account is private Leíste un campo que no es pub desde fuera de su módulo
E0451 field x of struct Y is private Creaste un struct con un literal, pero algunos de sus campos son privados
E0624 method x is private Llamaste a un método o a una función asociada que no es pub
E0283 type annotations needed (cannot infer type … multiple impls satisfy this bound) Podrían encajar varios tipos (por ejemplo, con .collect() o .sum()), así que tienes que elegir uno
E0284 type annotations needed: cannot satisfy <_ as FromStr>::Err == _ "42".parse() no sabe a qué tipo convertir el texto
E0790 cannot call associated function on trait without specifying the corresponding impl type Escribiste Default::default() o Trait::new() sin decir de qué tipo
E0559 variant Shape::Circle has no field named r Al crear una variante de enum usaste un nombre de campo que esa variante no tiene
E0063 missing field email in initializer of User Creaste un struct pero te faltó uno o más campos
E0689 can’t call method pow on ambiguous numeric type {integer} 2.pow(10) o 2.0.sqrt() necesita un tipo numérico concreto, como i32 o f64
E0034 multiple applicable items in scope Dos traits le dan a tu tipo un método con el mismo nombre, y Rust no puede elegir uno
E0412 cannot find type X in this scope (Rust 1.93+ prints E0425) Un nombre de tipo está mal escrito, no está importado o no está declarado
E0428 the name area is defined multiple times Dos elementos comparten un nombre; Rust no tiene sobrecarga de funciones
E0026 variant Shape::Circle does not have a field named r Un patrón nombra un campo que el struct o la variante no tiene
E0027 pattern does not mention fields id, paid Un patrón de struct deja fuera campos; añádelos o termina con ..
E0533 expected unit struct, unit variant or constant, found struct variant Shape::Circle Usas una variante de struct (o una función) donde se espera un nombre simple; añade { .. }
E0592 duplicate definitions with name reset Dos bloques impl definen un método con el mismo nombre
E0255 the name Error is defined multiple times Un import con use tiene el mismo nombre que un tipo o una función tuyos
E0252 the name Result is defined multiple times Dos líneas use traen el mismo nombre; renombra una con as
E0411 cannot find type Self in this scope Usaste Self fuera de un impl o de un trait
E0405 cannot find trait Display in this scope El nombre de un trait está mal escrito o no está importado (p. ej. use std::fmt::Display;)
E0532 expected unit struct, unit variant or constant, found tuple variant Shape::Circle Un patrón nombra una variante de tupla (o un struct) sin sus ( ), o añade ( ) donde no van
E0164 expected tuple struct or tuple variant, found struct variant Shape::Circle Un patrón usa ( ) en una variante de struct o en un elemento asociado; usa { } o una guarda
E0404 expected trait, found derive macro Debug Escribiste impl X for o T: X donde X es un struct, un alias o una macro derive sin importar
E0401 can’t use generic parameters from outer item Una fn interna usa el T o el Self de la función externa; dale sus propios genéricos o usa una closure
E0107 enum takes 2 generic arguments but 1 generic argument was supplied Result<u32>, HashMap<String> y compañía: faltan o sobran argumentos entre < >
E0530 match bindings cannot shadow tuple variants Un nombre de variante suelto, como Circle => (después de use Shape::*), no puede ser una variable nueva
E0434 can’t capture dynamic environment in a fn item Una fn interna no ve las variables locales de la función externa; usa una closure o pásaselas como argumento
E0601 main function not found in crate main El binario no tiene fn main() (falta, está mal escrita, está dentro de un mod o en realidad es una biblioteca)
E0658 use of unstable library feature iter_intersperse Usaste una API solo de nightly en Rust estable; usa la alternativa estable o actualiza Rust
E0614 type u32 cannot be dereferenced Escribiste *x cuando x ya es un valor normal, no una referencia
E0435 attempt to use a non-constant value in a constant Un const, la longitud de un array o un static usa una variable let; conviértela en const o usa un Vec
E0554 #![feature] may not be used on the stable release channel Código copiado que solo funciona en nightly; quita el atributo y usa la API estable, o usa nightly a propósito

Los mensajes de error de Rust tienen fama de ser muy útiles, pero meten mucha información en poco espacio. Aquí tienes uno real:

fn main() {
let name = String::from("Ferris");
let greeting = name;
println!("{name}");
}
error[E0382]: borrow of moved value: `name`
--> src/main.rs:4:16
|
2 | let name = String::from("Ferris");
| ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait
3 | let greeting = name;
| ---- value moved here
4 | println!("{name}");
| ^^^^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
3 | let greeting = name.clone();
| ++++++++

El compilador dice que name se movió en la línea 3 y que en la línea 4 se intenta usar otra vez, y sugiere clonarlo. Léelo en este orden:

  1. La primera línea es el resumen: el código de error (E0382) y una descripción de una línea.
  2. La línea de la flecha (--> src/main.rs:4:16) te dice el archivo, la línea y la columna donde algo salió mal.
  3. Las marcas ^^^^ señalan el punto exacto del error. Las marcas ---- cuentan la historia que lleva hasta él. Aquí dicen: el valor se creó en la línea 2, se movió en la línea 3 y se usó en la línea 4.
  4. help: es la solución que sugiere el compilador, a menudo con el código exacto que hay que añadir (las marcas ++++ muestran los caracteres nuevos). No siempre es la mejor solución, pero es un punto de partida excelente.

Empieza siempre por el primer error. Un solo fallo puede provocar una cadena de errores que vienen detrás, y al arreglar el primero muchas veces desaparecen los demás.

  • Pídele más detalles al compilador. Cada código de error trae una explicación más larga incorporada. Ejecuta esto en una terminal:

    Terminal window
    rustc --explain E0382

    Obtendrás una descripción corta, un ejemplo que falla y otro corregido (en inglés).

  • Compila a menudo. cargo check encuentra los errores sin construir todo el programa, así que es mucho más rápido que cargo build. Si lo ejecutas cada pocas líneas, te encuentras los errores de uno en uno, no veinte de golpe. Mira Cargo y crates.

  • Deja que tu editor te muestre los errores mientras escribes. Con la extensión rust-analyzer, los errores aparecen directamente en tu código, con el mismo texto de ayuda. Mira Herramientas de Rust.

La mayoría de estos errores existen porque Rust comprueba, antes de que tu programa se ejecute, cosas que otros lenguajes solo descubren en tiempo de ejecución (o nunca): usar memoria ya liberada, dos hilos cambiando los mismos datos, una comprobación de null que falta. Cada error que arreglas es un bug que nunca llegará a tus usuarios.

Por eso mucha gente dice que en Rust la pelea ocurre al compilar, y después el programa simplemente funciona. Las reglas que hay detrás de los errores más comunes se explican en Ownership, Borrowing y Lifetimes.

Comprueba lo aprendido

1. Un error de Rust muestra varios problemas. ¿Cuál deberías arreglar primero?

2. ¿Qué hace rustc --explain E0382?

3. En un mensaje de error, ¿qué indican las marcas ^^^^?

Puntuación: 0 / 3