Ir al contenido

Error E0532 de Rust: expected unit struct, unit variant or constant, found tuple variant

E0532 significa: la forma de tu patrón no coincide con la forma de lo que nombraste. El caso clásico es una rama de match como Shape::Circle => para una variante que guarda datos, Circle(f64). Rust quiere los paréntesis: Shape::Circle(_). El error contrario tiene el mismo código, con otro texto, “expected tuple struct or tuple variant”: paréntesis detrás de algo que no lleva datos entre paréntesis, como Status::Active(). Los dos se arreglan en una línea. (Esta página forma parte de Errores del compilador de Rust explicados.)

error[E0532]: expected unit struct, unit variant or constant, found tuple variant `Shape::Circle`
--> src/main.rs:8:9
|
2 | Circle(f64),
| ----------- `Shape::Circle` defined here
...
8 | Shape::Circle => "circle", // ❌ `Circle` holds a value
| ^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `Shape::Circle(_)`

En español: “se esperaba un struct unitario, una variante unitaria o una constante, pero se encontró la variante de tupla Shape::Circle”. El help te propone la sintaxis correcta.

Este es el programa que lo produce:

enum Shape {
Circle(f64),
Square(f64),
}
fn name(shape: &Shape) -> &'static str {
match shape {
Shape::Circle => "circle", // ❌ `Circle` holds a value
Shape::Square(_) => "square",
}
}
fn main() {
println!("{}", name(&Shape::Circle(1.0)));
}

El ^^^ señala Shape::Circle en la línea 8, y el --- de la línea 2 muestra cómo se definió: Circle(f64), una variante de tupla (tuple variant) que lleva un f64. Un patrón que es solo un nombre, sin nada detrás, tiene que ser una de estas tres cosas:

  • un struct unitario (unit struct), como struct Empty;
  • una variante unitaria (unit variant), una variante sin datos, como Shape::Empty o None
  • una constante, como const LIMIT: u32 = 100;

Shape::Circle no es ninguna de ellas. La línea help te da la solución directamente: Shape::Circle(_), es decir, “un círculo, tenga el valor que tenga”.

El otro titular de E0532 es el reflejo de este: expected tuple struct or tuple variant, found unit variant `Status::Active` (o found struct, o found constant). Ahí fuiste tú quien puso paréntesis detrás de un nombre, y lo que nombraste no recibe valores entre paréntesis.

Es como un formulario que pide “Mascota: perro (nombre: ____)”. Si escribes solo “perro”, dejas vacía la casilla del nombre. Y si escribes “pez (nombre: Burbujas)” donde el formulario solo dice “pez”, sin casilla, estás añadiendo una casilla que no existe.

Cada struct y cada variante de enum tiene una de tres formas, y se escribe igual al crearla que al hacer match con ella (mira Los enums pueden guardar datos):

Tipo Crearla Hacer match
Unitaria: Empty Shape::Empty Shape::Empty
De tupla: Circle(f64) Shape::Circle(1.0) Shape::Circle(r) o Shape::Circle(..)
De struct: Rect { w: f64, h: f64 } Shape::Rect { w: 2.0, h: 3.0 } Shape::Rect { w, h } o Shape::Rect { .. }

Como las formas son estrictas, un patrón siempre se parece al valor con el que encaja, y puedes leer un match y ver qué datos tiene cada rama. También ayuda cuando cambias un tipo: si más adelante Empty pasa a guardar un valor y se convierte en Empty(u32), Rust marca cada rama antigua Shape::Empty, en lugar de dejar que encaje en silencio con algo nuevo.

Solución 1: Añade (_), (..) o nombres para los valores

Sección titulada «Solución 1: Añade (_), (..) o nombres para los valores»

Elige esta cuando el mensaje dice found tuple variant o found tuple struct, que es el E0532 más común. Usa _ por cada valor que no necesites, .. para saltarte todos de una vez, o un nombre cuando quieras usar el valor:

enum Shape {
Circle(f64),
Rect(f64, f64),
Empty,
}
fn name(shape: &Shape) -> &'static str {
match shape {
Shape::Circle(_) => "círculo", // ✅ un campo, ignorado
Shape::Rect(..) => "rectángulo", // ✅ cualquier número de campos, todos ignorados
Shape::Empty => "nada", // una variante unitaria: sin paréntesis
}
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle(r) => 3.14 * r * r, // ✅ le damos nombre al campo porque lo necesitamos
Shape::Rect(w, h) => w * h,
Shape::Empty => 0.0,
}
}
fn main() {
let shapes = [Shape::Circle(1.0), Shape::Rect(2.0, 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.14
rectángulo: 6.00
nada: 0.00
1 círculo(s)
▶ Pruébalo tú mismo

(..) es práctico para variantes con varios valores, y sigue funcionando si más adelante añades uno más. Mira Ignorar partes con _ y ...

Solución 2: Quita los () de una variante unitaria

Sección titulada «Solución 2: Quita los () de una variante unitaria»

Elige esta cuando el mensaje dice found unit variant o found unit struct. La variante no guarda datos, así que no hay nada que poner entre paréntesis:

error[E0532]: expected tuple struct or tuple variant, found unit variant `Status::Active`
--> src/main.rs:8:9
|
2 | Active,
| ------ `Status::Active` defined here
...
8 | Status::Active() => "active", // ❌ `Active` holds no data
| ^^^^^^^^^^^^^^^^ help: use this syntax instead: `Status::Active`

“Se esperaba un tuple struct o una variante de tupla, pero se encontró la variante unitaria Status::Active”. El programa que lo produce:

enum Status {
Active,
Banned(String),
}
fn label(s: &Status) -> &'static str {
match s {
Status::Active() => "active", // ❌ `Active` holds no data
Status::Banned(_) => "banned",
}
}
fn main() {
println!("{}", label(&Status::Active));
}

Escribe solo el nombre, tanto en el patrón como donde creas el valor:

#[derive(Debug)]
enum Status {
Active,
Banned(String),
}
fn label(s: &Status) -> String {
match s {
Status::Active => String::from("activo"), // ✅ variante unitaria: sin ()
Status::Banned(reason) => format!("bloqueado ({})", reason),
}
}
fn main() {
println!("{}", label(&Status::Active));
println!("{}", label(&Status::Banned(String::from("spam"))));
let s = Status::Active; // ✅ y tampoco lleva () cuando la creas
println!("{:?}", s);
}

Salida:

activo
bloqueado (spam)
Active
▶ Pruébalo tú mismo

Si querías que la variante llevara datos, cambia la definición, por ejemplo Active(u64) para guardar desde cuándo está activa, y entonces Status::Active(_) es el patrón correcto.

Solución 3: Usa llaves para un struct con campos con nombre

Sección titulada «Solución 3: Usa llaves para un struct con campos con nombre»

Elige esta cuando el mensaje dice found struct. Un struct con campos con nombre, struct Point { x: i32, y: i32 }, se desestructura con llaves y los nombres de los campos, no con paréntesis:

error[E0532]: expected tuple struct or tuple variant, found struct `Point`
--> src/main.rs:8:9
|
1 | / struct Point {
2 | | x: i32,
3 | | y: i32,
4 | | }
| |_- `Point` defined here
...
8 | let Point(x, y) = p; // ❌ `Point` has named fields
| ^^^^^^^^^^^ help: use struct pattern syntax instead: `Point { x, y }`

El programa que lo produce:

struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 3, y: 4 };
let Point(x, y) = p; // ❌ `Point` has named fields
println!("{} {}", x, y);
}

La sugerencia de rustc, Point { x, y }, es exactamente la correcta. Usa campo: nombre cuando quieras otro nombre de variable:

struct Point {
x: i32,
y: i32,
}
struct Meters(f64); // un tuple struct: aquí los paréntesis sí son correctos
fn main() {
let p = Point { x: 3, y: 4 };
let Point { x, y } = p; // ✅ llaves y los nombres de los campos
println!("x = {}, y = {}", x, y);
let q = Point { x: -1, y: 7 };
let Point { x: left, y: up } = q; // ✅ cambia el nombre al desestructurar
println!("left = {}, up = {}", left, up);
let Meters(m) = Meters(2.5); // ✅ tuple struct, patrón de tupla
println!("{} m", m);
}

Salida:

x = 3, y = 4
left = -1, up = 7
2.5 m
▶ Pruébalo tú mismo

Para una variante de enum con campos con nombre, como Shape::Rect(w, h) para Rect { w: f64, h: f64 }, el mismo error da otro código, E0164. La solución es la misma: llaves.

Solución 4: Usa una constante o una guarda en lugar de una llamada a función

Sección titulada «Solución 4: Usa una constante o una guarda en lugar de una llamada a función»

Elige esta cuando el mensaje dice expected a pattern, found a function call (se esperaba un patrón, se encontró una llamada a función). Un patrón tiene que conocerse al compilar, y una llamada a función no:

error[E0532]: expected a pattern, found a function call
--> src/main.rs:7:14
|
7 | Some(limit()) => "full", // ❌ a function call can't be a pattern
| ^^^^^ not a tuple struct or tuple variant
|
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>

La note lo dice claro: no se permiten llamadas a funciones en los patrones. El programa que lo produce:

fn limit() -> u32 {
100
}
fn status(users: Option<u32>) -> &'static str {
match users {
Some(limit()) => "full", // ❌ a function call can't be a pattern
Some(_) => "open",
None => "closed",
}
}
fn main() {
println!("{}", status(Some(100)));
}

Si el valor nunca cambia, conviértelo en un const: las constantes sí pueden ir dentro de un patrón. Si hay que calcularlo, dale un nombre al valor y compáralo en una guarda (match guard):

const LIMIT: u32 = 100; // una constante puede ir dentro de un patrón
fn limit_for(premium: bool) -> u32 {
if premium { 500 } else { 100 }
}
fn status(users: Option<u32>) -> &'static str {
match users {
Some(LIMIT) => "lleno", // ✅ una constante
Some(_) => "abierto",
None => "cerrado",
}
}
fn status_for(users: Option<u32>, premium: bool) -> &'static str {
match users {
Some(n) if n >= limit_for(premium) => "lleno", // ✅ llama a la función en una guarda
Some(_) => "abierto",
None => "cerrado",
}
}
fn main() {
println!("{}", status(Some(100)));
println!("{}", status(Some(42)));
println!("{}", status(None));
println!("{}", status_for(Some(100), false));
println!("{}", status_for(Some(100), true));
}

Salida:

lleno
abierto
cerrado
lleno
abierto
▶ Pruébalo tú mismo

Las guardas se explican en Guardas: añadir un if.

Después de que una variante unitaria pase a guardar un valor. Event::Logout era una variante unitaria y la cambiaste a Logout(u64). Ahora cada rama Event::Logout => da E0532. Solución: Event::Logout(_) =>, o Event::Logout(at) => si necesitas el valor.

Comprobar solo de qué tipo es un valor. Si vienes de Java o TypeScript, quizá escribas if let Shape::Circle = shape para preguntar “¿es un círculo?”. Escribe if let Shape::Circle(_) = shape, o matches!(shape, Shape::Circle(_)) para obtener un bool rápido.

Sin el prefijo Shape:: es E0530. Si escribes un nombre suelto, como Ok => o Circle => después de use Shape::*;, rustc lo lee como una variable nueva. Muestra E0530, match bindings cannot shadow tuple variants (los enlaces de un match no pueden ocultar variantes de tupla), con el help try specify the pattern arguments: `Ok(..)` . La solución es la misma: añade los paréntesis.

Comprueba lo aprendido

1. Para enum Shape { Circle(f64), Empty }, ¿qué rama de match compila?

2. rustc dice "expected tuple struct or tuple variant, found unit variant Status::Active". ¿Cómo se arregla?

3. struct Point { x: i32, y: i32 }: ¿cómo lo desestructuras con let?

Puntuación: 0 / 3