Error E0533 de Rust: expected unit struct, unit variant or constant, found struct variant
E0533 significa: escribiste un nombre como Shape::Circle solo, pero ese nombre necesita algo más que su nombre para usarse ahí. Casi siempre es una variante de enum con campos con nombre (Circle { radius: f64 }) escrita sin sus { }, ya sea en un brazo de match o al crear un valor. Menos a menudo es una función o un método escrito donde solo puede ir un valor fijo. Las dos cosas se arreglan rápido en cuanto sabes qué te pide rustc. (Esta página forma parte de Errores del compilador de Rust explicados.)
El mensaje de error
Sección titulada «El mensaje de error»error[E0533]: expected unit struct, unit variant or constant, found struct variant `Shape::Circle` --> src/main.rs:8:9 |8 | Shape::Circle => "circle", // ❌ `Circle` has a field | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant |help: the struct variant's field is being ignored |8 | Shape::Circle { radius: _ } => "circle", // ❌ `Circle` has a field | +++++++++++++“Expected unit struct, unit variant or constant, found struct variant” quiere decir “se esperaba un unit struct, una variante unitaria o una constante, y se encontró una variante de struct”. El help te avisa de que el campo de la variante se está ignorando, y te muestra cómo escribirlo con llaves.
Este es el programa que lo produce:
enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle => "circle", // ❌ `Circle` has a field Shape::Square { .. } => "square", }}
fn main() { println!("{}", name(&Shape::Square { side: 2.0 }));}Qué significa
Sección titulada «Qué significa»El ^^^ señala Shape::Circle, y el titular explica qué se permitía ahí: un patrón que es solo un nombre tiene que ser una de estas tres cosas:
- un unit struct (struct sin campos), como
struct Empty; - una variante unitaria, una variante sin datos, como
Shape::EmptyoNone - una constante, como
const MAX: u32 = 100;
Shape::Circle no es ninguna de ellas. Es una variante de struct: lleva un radius. Un Shape::Circle a secas coincidiría con “un círculo”, pero no diría nada de su campo, y Rust quiere que la forma del patrón coincida con la forma de la variante. La línea help: te enseña la solución: añade las llaves.
La segunda clase de E0533 dice expected value, found struct variant (se esperaba un valor, se encontró una variante de struct). Es la misma confusión, pero al crear un valor, normalmente escrito con paréntesis, como Shape::Circle(2.0).
Es como un formulario de paquetería con una casilla que dice “Tamaño: S, M o L”, y tú escribiste “A medida”. “A medida” es una opción real, pero necesita que rellenes las medidas al lado.
Por qué Rust hace esto
Sección titulada «Por qué Rust hace esto»Las variantes de un enum tienen tres formas, y cada una se escribe a su manera, tanto al crearla como al hacer match con ella (mira Los enums pueden guardar datos):
| Variante | Crearla | Hacer match con ella |
|---|---|---|
Unitaria: Empty |
Shape::Empty |
Shape::Empty |
De tupla: Point(f64, f64) |
Shape::Point(1.0, 2.0) |
Shape::Point(x, y) o Shape::Point(..) |
De struct: Circle { radius: f64 } |
Shape::Circle { radius: 2.0 } |
Shape::Circle { radius } o Shape::Circle { .. } |
Mantener estas formas estrictas hace que un patrón siempre se parezca a lo que compara, así que puedes leer un match y saber exactamente qué datos tiene cada brazo. También significa que, cuando una variante cambia de forma, por ejemplo cuando Empty gana un campo, cada sitio que usa la forma antigua queda señalado en lugar de hacer algo equivocado sin avisar.
Cómo solucionarlo
Sección titulada «Cómo solucionarlo»Solución 1: Añade { .. } o los campos al patrón
Sección titulada «Solución 1: Añade { .. } o los campos al patrón»Elige esta cuando el error señala un brazo de match, if let o matches! y dice found struct variant. Escribe { .. } si no necesitas los campos, o nómbralos si los necesitas. La sugerencia de rustc, { radius: _ }, también funciona, y { .. } es la forma más corta de decir lo mismo.
enum Shape { Circle { radius: f64 }, Square { side: f64 }, Empty,}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle { .. } => "círculo", // ✅ "un círculo, tenga el radio que tenga" Shape::Square { .. } => "cuadrado", Shape::Empty => "nada", // una variante unitaria: no necesita llaves }}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ campos nombrados porque los necesitamos Shape::Square { side } => side * side, Shape::Empty => 0.0, }}
fn main() { let shapes = [Shape::Circle { radius: 1.0 }, Shape::Square { side: 3.0 }, Shape::Empty]; for shape in &shapes { println!("{}: {:.2}", name(shape), area(shape)); } let circles = shapes.iter().filter(|s| matches!(s, Shape::Circle { .. })).count(); println!("{} círculo(s)", circles);}Salida:
círculo: 3.14cuadrado: 9.00nada: 0.001 círculo(s){ .. } funciona con cualquier variante de struct, tenga los campos que tenga. Para las variantes de tupla, la misma idea se escribe (..). Mira Ignorar partes con _ y ...
Solución 2: Crea el valor con llaves y nombres de campos
Sección titulada «Solución 2: Crea el valor con llaves y nombres de campos»Elige esta cuando el mensaje dice expected value, found struct variant. Estás creando una variante de struct como si fuera una variante de tupla (o sin ningún campo):
error[E0533]: expected value, found struct variant `Shape::Circle` --> src/main.rs:8:17 |8 | let shape = Shape::Circle(2.0); // ❌ `Circle` has a named field | ^^^^^^^^^^^^^ not a value |help: you might have meant to create a new value of the struct |8 - let shape = Shape::Circle(2.0); // ❌ `Circle` has a named field8 + let shape = Shape::Circle { radius: /* value */ }; // ❌ `Circle` has a named field |La etiqueta not a value significa “no es un valor”, y el help dice que quizá querías crear un valor nuevo del struct, con la línea ya escrita con llaves.
El programa que hay detrás:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn main() { let shape = Shape::Circle(2.0); // ❌ `Circle` has a named field println!("{:?}", shape);}El /* value */ de la sugerencia es un hueco para tu valor. Los campos de una variante de struct se asignan por su nombre, dentro de llaves:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
impl Shape { // un constructor corto, si quieres escribir `Shape::circle(2.0)` fn circle(radius: f64) -> Shape { Shape::Circle { radius } }}
fn main() { let a = Shape::Circle { radius: 2.0 }; // ✅ llaves y el nombre del campo let b = Shape::Square { side: 1.5 }; let c = Shape::circle(0.5); println!("{:?}", a); println!("{:?}", b); println!("{:?}", c);}Salida:
Circle { radius: 2.0 }Square { side: 1.5 }Circle { radius: 0.5 }Si prefieres escribir Shape::Circle(2.0), cambia la definición a una variante de tupla: Circle(f64). Es una buena opción para un solo campo evidente; los campos con nombre son más claros cuando hay varios.
Solución 3: Usa una constante o una guarda en lugar de una función
Sección titulada «Solución 3: Usa una constante o una guarda en lugar de una función»Elige esta cuando el mensaje dice found associated function (se encontró una función asociada). También aparece con métodos, como String::len. Un patrón tiene que ser un valor que se conoce al compilar. Una llamada a una función no lo es, así que el nombre de una función no puede usarse como patrón:
error[E0533]: expected unit struct, unit variant or constant, found associated function `Limits::max_users` --> src/main.rs:12:9 |12 | Limits::max_users => "full", // ❌ a function can't be a pattern | ^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constantRust esperaba un unit struct, una variante unitaria o una constante, y encontró la función asociada Limits::max_users.
El programa que hay detrás:
struct Limits;
impl Limits { fn max_users() -> u32 { 100 }}
fn status(users: u32) -> &'static str { match users { 0 => "empty", Limits::max_users => "full", // ❌ a function can't be a pattern _ => "open", }}
fn main() { println!("{}", status(100));}Si el valor nunca cambia, conviértelo en un const. Las constantes sí pueden ser patrones. Si hay que calcularlo, quédate con la función y compara en una guarda (match guard) con if:
struct Limits;
impl Limits { const MAX_USERS: u32 = 100; // una constante se puede usar como patrón
fn max_rooms(premium: bool) -> u32 { if premium { 20 } else { 5 } }}
fn status(users: u32) -> &'static str { match users { 0 => "vacío", Limits::MAX_USERS => "lleno", // ✅ una constante _ => "abierto", }}
fn rooms_status(rooms: u32, premium: bool) -> &'static str { match rooms { n if n >= Limits::max_rooms(premium) => "no caben más salas", // ✅ la llamas en una guarda _ => "puedes añadir una sala", }}
fn main() { println!("{}", status(0)); println!("{}", status(100)); println!("{}", status(42)); println!("{}", rooms_status(5, false)); println!("{}", rooms_status(5, true));}Salida:
vacíollenoabiertono caben más salaspuedes añadir una salaLas guardas se explican en Guardas: añadir un if.
Dónde lo verás normalmente
Sección titulada «Dónde lo verás normalmente»Después de que una variante unitaria gane campos. Status::Done era una variante unitaria, y la cambiaste a Done { at: u64 }. Ahora cada brazo Status::Done => y cada let s = Status::Done; da E0533. Solución: Status::Done { .. } => en los patrones, y Status::Done { at: 0 } (con un valor real) donde lo creas.
Si vienes de otro lenguaje. En Java o TypeScript quizá escribirías case Circle: para comprobar solo de qué clase es un valor. En Rust, escribe Shape::Circle { .. } =>, o matches!(shape, Shape::Circle { .. }) para obtener un bool rápido.
La versión para variantes de tupla. Con una variante de tupla como Circle(f64), un brazo Shape::Circle => a secas da otro código, E0532, con el mismo titular: “expected unit struct, unit variant or constant, found tuple variant Shape::Circle” (se encontró una variante de tupla). La solución es Shape::Circle(_) o Shape::Circle(..). Y poner paréntesis a una variante de struct en un patrón, como Shape::Circle(r) => para Circle { radius: f64 }, da E0164, “expected tuple struct or tuple variant, found struct variant” (se esperaba un tuple struct o una variante de tupla, se encontró una variante de struct). Solución: Shape::Circle { radius: r } =>.
Errores relacionados
Sección titulada «Errores relacionados»- E0559: variant has no field named x: las llaves están bien, pero un nombre de campo dentro de ellas está mal.
- E0026: struct or variant does not have a field named x: un nombre de campo equivocado dentro de las llaves de un patrón.
- E0027: pattern does not mention field x: llaves en un patrón que dejan campos fuera; añade
... - E0004: non-exhaustive patterns: después de corregir los brazos, el
matchtodavía tiene que cubrir todas las variantes. E0532: expected unit struct, unit variant or constant, found tuple variant: la versión para variantes de tupla (mira más 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. Con enum Shape { Circle { radius: f64 } }, ¿qué brazo de match compila?
2. let s = Shape::Circle(2.0); da "expected value, found struct variant". ¿Cuál es la solución?
3. ¿Cuál de estos se puede usar solo como patrón de un match?
Puntuación: 0 / 3
Para leer más
Sección titulada «Para leer más»- E0533 — Rust error codes index (en inglés): la explicación oficial de este error.
- Pattern Syntax — El libro de Rust (en inglés): desestructurar enums, ignorar valores con
..y las guardas. También existe una traducción al español de la comunidad del libro. - Destructuring enums — Rust by Example (en inglés): variantes unitarias, de tupla y de struct en un mismo
match. - E0532 — Rust error codes index (en inglés): la página oficial de la versión de este error para variantes de tupla.
- Patterns — The Rust Reference (en inglés): qué rutas se permiten como patrones, y las reglas de los patrones de structs y de tuple structs.