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.
Los errores más comunes
Sección titulada «Los errores más comunes»| 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 |
Cómo leer un error de Rust
Sección titulada «Cómo leer un error de Rust»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` trait3 | let greeting = name; | ---- value moved here4 | 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:
- La primera línea es el resumen: el código de error (
E0382) y una descripción de una línea. - 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. - 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. 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.
Tres hábitos que ayudan
Sección titulada «Tres hábitos que ayudan»-
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 E0382Obtendrás una descripción corta, un ejemplo que falla y otro corregido (en inglés).
-
Compila a menudo.
cargo checkencuentra los errores sin construir todo el programa, así que es mucho más rápido quecargo 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.
Por qué Rust tiene tantos errores
Sección titulada «Por qué Rust tiene tantos errores»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 que aprendiste
Sección titulada «Comprueba lo que aprendiste»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
Para leer más
Sección titulada «Para leer más»- Rust Compiler Error Index (en inglés): la lista oficial de todos los códigos de error, cada uno con un ejemplo que falla y otro corregido.
- Understanding Ownership — El libro de Rust (en inglés): las reglas que hay detrás de los errores más comunes al mover y tomar prestados valores. También existe una traducción al español de la comunidad del libro.
- Error Handling — El libro de Rust (en inglés): cómo maneja Rust los errores dentro de tus propios programas (
Resultypanic!), no solo los del compilador. - What is rustc? — The rustc Book (en inglés): cómo funciona el compilador, incluidas sus opciones y sus niveles de lints.