E0382
error[E0382]: use of moved value: `s1`
Cuando asignas un valor asignado en el montón (como String o Vec) a otra variable, la propiedad se mueve a la nueva variable. El original desaparece — no puedes usarlo después. Este es el sistema de ownership de Rust eliminando los errores de use-after-free en tiempo de compilación.
❌ Broken
let s1 = String::from("hello");
let s2 = s1; // s1 moves into s2
println!("{}", s1); // ❌ E0382: s1 was moved✅ Fixed
let s1 = String::from("hello");
let s2 = s1.clone(); // deep copy — both stay valid
println!("{} {}", s1, s2); // ✅
// Or borrow instead of moving:
let s2 = &s1;
println!("{} {}", s1, s2); // ✅💡 Tip: Los tipos primitivos (i32, bool, char, f64) implementan Copy y se duplican automáticamente. Los tipos en el montón (String, Vec, Box) se mueven.
E0502
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
Rust permite muchas referencias compartidas (&) O una exclusiva (&mut) — nunca ambas al mismo tiempo. Si tienes un préstamo inmutable activo, no puedes tomar un préstamo mutable hasta que el inmutable termine. Esta regla elimina las condiciones de carrera por construcción.
❌ Broken
let mut v = vec![1, 2, 3];
let first = &v[0]; // immutable borrow
v.push(4); // ❌ E0502: mutable borrow while immutable exists
println!("{}", first);✅ Fixed
let mut v = vec![1, 2, 3];
let first = v[0]; // copy the value out (i32 is Copy)
v.push(4); // ✅ no active borrow
println!("{}", first);
// Or restructure scope:
let mut v = vec![1, 2, 3];
{
let first = &v[0];
println!("{}", first);
} // first's borrow ends here
v.push(4); // ✅💡 Tip: El borrow checker es conservador. Si te está complicando, intenta mover el println antes, copiar el valor en lugar de prestarlo, o usar .clone().
E0499
error[E0499]: cannot borrow `v` as mutable more than once at a time
Solo puede existir una referencia mutable (&mut) a la vez. Esto previene las condiciones de carrera en código de un solo hilo y es la regla fundamental que hace funcionar las garantías de concurrencia de Rust.
❌ Broken
let mut v = vec![1, 2, 3];
let a = &mut v;
let b = &mut v; // ❌ E0499: second mutable borrow
a.push(4);
b.push(5);
✅ Fixed
let mut v = vec![1, 2, 3];
{
let a = &mut v;
a.push(4);
} // a's borrow ends here
let b = &mut v; // ✅ now safe
b.push(5);💡 Tip: Usa ámbitos {} para limitar cuánto tiempo vive un préstamo mutable. En la práctica, este error a menudo significa reestructurar la lógica para que las mutaciones ocurran de forma secuencial.
E0308
error[E0308]: mismatched types
expected `i32`, found `&i32`
El tipo que el compilador infirió o espera no coincide con lo que proporcionaste. Muy común al iterar (los iteradores producen referencias), cuando una función devuelve () en lugar de un valor, o al mezclar enteros con y sin signo.
❌ Broken
// Trailing semicolon returns () instead of i32:
fn double(n: i32) -> i32 {
n * 2; // ❌ E0308: returns () not i32
}
// Iterator reference confusion:
let nums = vec![1, 2, 3];
let sum: i32 = nums.iter().sum(); // needs type annotation✅ Fixed
fn double(n: i32) -> i32 {
n * 2 // ✅ no semicolon — expression returned
}
// Dereference in closures when iterating:
let nums = vec![1, 2, 3];
let doubled: Vec<i32> = nums.iter().map(|&x| x * 2).collect();
// ^ dereference the &i32💡 Tip: Un punto y coma final en la última línea de una función cambia silenciosamente el tipo de retorno a (). Este es el error número 1 de los principiantes en Rust.
E0277
error[E0277]: `MyType` doesn't implement `std::fmt::Display`
El tipo no implementa un trait requerido. Más frecuentemente se activa al intentar usar el formato {} sin Display, al intentar comparar tipos sin PartialOrd, o al llamar a métodos que requieren un trait específico.
❌ Broken
struct Point { x: i32, y: i32 }
let p = Point { x: 1, y: 2 };
println!("{}", p); // ❌ E0277: Point doesn't implement Display
println!("{:?}", p); // also fails — needs Debug✅ Fixed
#[derive(Debug)]
struct Point { x: i32, y: i32 }
let p = Point { x: 1, y: 2 };
println!("{:?}", p); // ✅ Debug via #[derive(Debug)]
// Implement Display manually for custom formatting:
use std::fmt;
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
println!("{}", p); // ✅💡 Tip: Añade #[derive(Debug)] para la impresión con {:?}. Para la impresión con {}, implementa std::fmt::Display manualmente. Los límites más faltantes son Debug, Display, Clone, PartialEq o PartialOrd.
E0106
error[E0106]: missing lifetime specifier
expected named lifetime parameter
Cuando una función devuelve una referencia y tiene múltiples parámetros de referencia, Rust no puede inferir de cuál entrada proviene la referencia de salida. Necesitas indicarlo con anotaciones de lifetime.
❌ Broken
// Compiler doesn't know if the return borrows from x or y:
fn longest(x: &str, y: &str) -> &str { // ❌ E0106
if x.len() > y.len() { x } else { y }
}✅ Fixed
// 'a says: output lives no longer than the shorter input
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { // ✅
if x.len() > y.len() { x } else { y }
}
// Single input → no annotation needed (elision rule):
fn first_word(s: &str) -> &str { // ✅ lifetime elided
let bytes = s.as_bytes();
for (i, &b) in bytes.iter().enumerate() {
if b == b' ' { return &s[..i]; }
}
&s[..]
}💡 Tip: Las anotaciones de lifetime son restricciones, no duraciones. 'a significa 'la salida no puede sobrevivir a las entradas'. La mayoría de los lifetimes se infieren (eliden). Solo necesitas los explícitos cuando el compilador no puede determinar la relación.
E0596
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
Intentaste modificar una variable que no fue declarada con mut. En Rust, las variables son inmutables por defecto — el compilador lo aplica para que las mutaciones accidentales se detecten en tiempo de compilación.
❌ Broken
let x = 5;
x = 10; // ❌ E0596: x is immutable
let v = vec![1, 2, 3];
v.push(4); // ❌ E0596: v is immutable
✅ Fixed
let mut x = 5; // ✅ mut makes it mutable
x = 10;
let mut v = vec![1, 2, 3];
v.push(4); // ✅
💡 Tip: Añade mut después de let. Añade mut solo cuando la variable genuinamente necesita cambiar — la inmutabilidad por defecto detecta errores y facilita razonar sobre el código.
E0384
error[E0384]: cannot assign twice to immutable variable `x`
Similar a E0596 pero activado por una segunda asignación en lugar de una llamada a método. La variable fue declarada sin mut pero intentaste reasignarla.
❌ Broken
let x = 5;
x = 10; // ❌ E0384
✅ Fixed
let mut x = 5;
x = 10; // ✅
// Shadowing is another option if you want to "replace" the variable:
let x = 5;
let x = 10; // ✅ shadowing — creates a new binding named x
💡 Tip: El shadowing (let x = ...) y la mutación (mut x = ...) se parecen pero son diferentes: el shadowing crea una nueva variable (y puede cambiar el tipo), la mutación modifica el mismo binding.
E0507
error[E0507]: cannot move out of `*s` which is behind a shared reference
Intentaste mover un valor fuera de una referencia. No puedes tomar posesión a través de un &T — la referencia no es dueña de los datos.
❌ Broken
fn print_name(s: &String) {
let owned = *s; // ❌ E0507: can't move out of &String
println!("{}", owned);
}✅ Fixed
fn print_name(s: &String) {
let owned = s.clone(); // ✅ clone the data
println!("{}", owned);
}
// Or just use the reference directly:
fn print_name(s: &String) {
println!("{}", s); // ✅ no need to own it
}💡 Tip: Si solo necesitas leer el valor, usa la referencia directamente. Si necesitas una copia propia, llama a .clone(). Si necesitas la propiedad, cambia el parámetro para que tome T en lugar de &T.
E0004
error[E0004]: non-exhaustive patterns: `None` not covered
Una expresión match debe manejar todos los casos posibles. Si alguna variante no se maneja, el código no compilará. Esto elimina toda una clase de errores en tiempo de ejecución donde los casos no manejados provocan fallos.
❌ Broken
let opt: Option<i32> = Some(42);
match opt {
Some(n) => println!("{}", n),
// ❌ E0004: None not covered
}✅ Fixed
match opt {
Some(n) => println!("{}", n),
None => println!("nothing"), // ✅ exhaustive
}
// Use _ as a catch-all:
match opt {
Some(n) => println!("{}", n),
_ => {}, // ✅ handles everything else
}
// Or use if let for a single case:
if let Some(n) = opt {
println!("{}", n); // ✅ no else needed
}💡 Tip: El compilador te dice exactamente qué variantes faltan. _ es un comodín. if let es una forma abreviada cuando solo te importa un patrón.
E0072
error[E0072]: recursive type `List` has infinite size
Un tipo recursivo donde cada variante se contiene directamente a sí misma requeriría memoria infinita para asignarse. Rust necesita conocer el tamaño de cada tipo en tiempo de compilación. La solución es la indirección mediante Box, que tiene un tamaño de puntero conocido.
❌ Broken
enum List {
Cons(i32, List), // ❌ E0072: infinite size
Nil,
}✅ Fixed
enum List {
Cons(i32, Box<List>), // ✅ Box has fixed pointer size (8 bytes)
Nil,
}
let list = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));💡 Tip: Box<T> es el puntero de montón más simple. Tiene un tamaño fijo (el ancho de un puntero) independientemente de T, rompiendo el cálculo de tamaño recursivo.
E0716
error[E0716]: temporary value dropped while borrowed
Creaste un valor temporal, tomaste una referencia a él y el temporal fue descartado antes de que se usara la referencia. La referencia quedaría colgante — apuntando a memoria liberada.
❌ Broken
let s: &str = &String::from("hello")
.to_uppercase(); // ❌ E0716: temporary dropped
// Also common with chains:
let name = get_user().name; // if get_user() returns a temp✅ Fixed
// Bind the temporary to a variable first:
let upper = String::from("hello").to_uppercase();
let s: &str = &upper; // ✅ upper lives long enough
println!("{}", s);💡 Tip: Si obtienes este error, introduce una variable para mantener el valor intermedio. El tiempo de vida de un binding let se extiende hasta el final del bloque.
E0515
error[E0515]: cannot return value referencing local variable `local`
Intentaste devolver una referencia a una variable local. Cuando la función retorna, la variable local se descarta, dejando una referencia colgante. Rust lo previene en tiempo de compilación.
❌ Broken
fn get_greeting() -> &str {
let s = String::from("hello");
&s // ❌ E0515: s is dropped when function returns
}✅ Fixed
// Return an owned value:
fn get_greeting() -> String {
String::from("hello") // ✅ caller owns it
}
// Or return a &'static str literal:
fn get_greeting() -> &'static str {
"hello" // ✅ lives for the entire program
}💡 Tip: Si necesitas devolver una referencia, debe provenir de las entradas de la función (prestando de un parámetro) o ser 'static. En caso de duda, devuelve un tipo propio (String, Vec, etc.).
E0369
error[E0369]: binary operation `>` cannot be applied to type `T`
Usaste un operador en un tipo genérico T, pero T no tiene un límite de trait que requiera que ese operador exista. El código genérico debe ser explícito sobre qué operaciones soporta un tipo.
❌ Broken
fn largest<T>(list: &[T]) -> &T {
let mut biggest = &list[0];
for item in list {
if item > biggest { // ❌ E0369: T doesn't implement PartialOrd
biggest = item;
}
}
biggest
}✅ Fixed
fn largest<T: PartialOrd>(list: &[T]) -> &T { // ✅ add bound
let mut biggest = &list[0];
for item in list {
if item > biggest {
biggest = item;
}
}
biggest
}💡 Tip: Cuando obtienes E0369, el mensaje de error te dice qué trait necesitas: PartialOrd para comparaciones, Add para +, Display para {}, etc. Añádelo como límite: <T: NombreDelTrait>.
E0428
error[E0428]: the name `connect` is defined multiple times
Definiste dos elementos (funciones, structs, tipos, etc.) con el mismo nombre en el mismo ámbito. Rust no lo permite — los nombres deben ser únicos dentro de un módulo.
❌ Broken
fn connect() -> String { "tcp".into() }
fn connect() -> String { "udp".into() } // ❌ E0428: duplicate✅ Fixed
fn connect_tcp() -> String { "tcp".into() }
fn connect_udp() -> String { "udp".into() } // ✅ unique names
// Or use a parameter:
fn connect(protocol: &str) -> String { protocol.into() }💡 Tip: Esto también ocurre con sentencias use que importan nombres en conflicto. Usa as para renombrar: use std::io::Error as IoError;
E0061
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
Llamaste a una función con más o menos argumentos de los que declara su firma. Rust no admite parámetros predeterminados ni funciones variádicas (excepto mediante macros como println!).
❌ Broken
fn add(a: i32, b: i32) -> i32 { a + b }
add(1, 2, 3); // ❌ E0061: 3 args, expected 2
add(1); // ❌ E0061: 1 arg, expected 2✅ Fixed
add(1, 2); // ✅
// For optional parameters, use Option:
fn greet(name: &str, title: Option<&str>) {
match title {
Some(t) => println!("{} {}", t, name),
None => println!("{}", name),
}
}
greet("Alice", None);
greet("Bob", Some("Dr."));💡 Tip: Rust no tiene parámetros predeterminados. Usa Option<T> para valores opcionales, o structs constructores para funciones con muchos campos opcionales.
E0433
error[E0433]: failed to resolve: use of undeclared crate or module `HashMap`
Usaste un tipo o función que no está en el ámbito. Para los tipos de la biblioteca estándar que no están en el preludio (como HashMap, BTreeMap, BufReader), necesitas una sentencia use explícita.
❌ Broken
let mut map = HashMap::new(); // ❌ E0433: HashMap not in scope
✅ Fixed
use std::collections::HashMap;
let mut map = HashMap::new(); // ✅
// Common imports:
use std::collections::{HashMap, HashSet, BTreeMap};
use std::io::{self, BufRead, Write};
use std::fmt;💡 Tip: El preludio de Rust importa automáticamente los tipos comunes (Vec, String, Option, Result, etc.). Todo lo demás necesita un use explícito. Rust Analyzer / rust-analyzer sugerirá la ruta use correcta.
error: expected `;`, found `let`
error: expected expression, found keyword `fn`
Errores de sintaxis — el analizador encontró algo inesperado. Generalmente un punto y coma faltante, un delimitador sin cerrar, un error tipográfico en una palabra clave o una expresión mal ubicada.
❌ Broken
fn main() {
let x = 5 // ❌ missing semicolon
let y = 10;
fn inner() {} // ❌ nested fn needs to be at statement level
x + y // if this is a statement, not a return, add ;
}✅ Fixed
fn main() {
let x = 5; // ✅ semicolon added
let y = 10;
fn helper() {} // ✅ nested fn is valid in Rust
println!("{}", x + y);
}💡 Tip: Los mensajes de error de Rust casi siempre apuntan a la línea correcta. Si un error de punto y coma parece incorrecto, revisa la línea anterior — un ; faltante en la declaración anterior pone al analizador en un estado extraño.
error[E0275]: overflow evaluating the requirement `Box<T>: Sized`
El compilador quedó atrapado en un bucle infinito intentando probar un límite de trait. Causado con mayor frecuencia por una implementación de trait recursiva o un tipo que intenta implementar un trait que se requiere a sí mismo.
❌ Broken
// Generic function calling itself with an incompatible bound:
fn process<T: Clone>(x: T) {
process(x.clone()); // infinite recursion in type inference
}✅ Fixed
// Add a base case or restructure logic:
fn process(x: String) {
if x.is_empty() { return; }
process(x[1..].to_string());
}💡 Tip: Este error casi siempre apunta a un tipo recursivo o a un bucle de límite de trait. Simplifica las restricciones del trait o añade parámetros de tipo explícitos.
error[E0425]: cannot find value `x` in this scope
Hiciste referencia a una variable que no existe en el ámbito actual. Causas comunes: error tipográfico en el nombre de la variable, variable declarada en un bloque interno que ya terminó, o una variable de bucle usada fuera del bucle.
❌ Broken
{
let x = 5;
}
println!("{}", x); // ❌ x is out of scope
for i in 0..10 { }
println!("{}", i); // ❌ i only lives inside the for loop✅ Fixed
let x = 5; // declare outside the block
{
println!("{}", x); // ✅ x is in scope
}
println!("{}", x); // ✅ still in scope
// Save the last loop value explicitly:
let mut last = 0;
for i in 0..10 { last = i; }
println!("{}", last); // ✅💡 Tip: El ámbito en Rust es por bloques. Las variables solo existen desde donde se declaran hasta el final de su bloque envolvente. Mueve la declaración hacia arriba si necesitas un ámbito más amplio.