Skip to content

Rust Error E0532: Expected Unit Struct, Unit Variant or Constant, Found Tuple Variant

E0532 means: the shape of your pattern doesn’t match the shape of the thing you named. The classic case is a match arm like Shape::Circle => for a variant that holds data, Circle(f64). Rust wants the parentheses: Shape::Circle(_). The reverse mistake gets the same code, with the other wording “expected tuple struct or tuple variant”: parentheses on something that has no data in parentheses, like Status::Active(). Both are one-line fixes. (This page is part of Rust compiler errors explained.)

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(_)`

This is the program that produces it:

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)));
}

The ^^^ points at Shape::Circle on line 8, and the --- on line 2 shows how it was defined: Circle(f64), a tuple variant that carries one f64. A pattern that is only a name, with nothing after it, must be one of three things:

  • a unit struct, like struct Empty;
  • a unit variant, a variant with no data, like Shape::Empty or None
  • a constant, like const LIMIT: u32 = 100;

Shape::Circle is none of these. The help line gives the fix right away: Shape::Circle(_), “a circle, whatever its value”.

The other E0532 headline is the mirror image: expected tuple struct or tuple variant, found unit variant `Status::Active` (or found struct, or found constant). There, you wrote parentheses after a name, and the thing you named doesn’t take values in parentheses.

It’s like a form that asks “Pet: dog (name: ____)”. Writing just “dog” leaves the name box empty, and writing “fish (name: Bubbles)” where the form says “fish” with no box adds a box that isn’t there.

Every struct and enum variant has one of three shapes, and you write it the same way when you create it and when you match on it (see Enums can hold data):

Kind Create it Match it
Unit: Empty Shape::Empty Shape::Empty
Tuple: Circle(f64) Shape::Circle(1.0) Shape::Circle(r) or Shape::Circle(..)
Struct: Rect { w: f64, h: f64 } Shape::Rect { w: 2.0, h: 3.0 } Shape::Rect { w, h } or Shape::Rect { .. }

Because the shapes are strict, a pattern always looks like the value it matches, and you can read a match and see what data each arm has. It also helps when you change a type: if Empty later gains a value and becomes Empty(u32), every old Shape::Empty arm is flagged, instead of quietly matching something new.

Fix 1: Add (_), (..) or names for the values

Section titled “Fix 1: Add (_), (..) or names for the values”

Choose this when the message says found tuple variant or found tuple struct, which is the most common E0532. Use _ for each value you don’t need, .. to skip all of them at once, or a name when you want to use the value:

enum Shape {
Circle(f64),
Rect(f64, f64),
Empty,
}
fn name(shape: &Shape) -> &'static str {
match shape {
Shape::Circle(_) => "circle", // ✅ one field, ignored
Shape::Rect(..) => "rectangle", // ✅ any number of fields, all ignored
Shape::Empty => "nothing", // a unit variant: no parentheses
}
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle(r) => 3.14 * r * r, // ✅ bind the field because we need it
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!("{} circle(s)", circles);
}

Output:

circle: 3.14
rectangle: 6.00
nothing: 0.00
1 circle(s)
▶ Try it Yourself

(..) is handy for variants with several values, and it keeps working if you add one more later. See Ignoring parts with _ and ...

Choose this when the message says found unit variant or found unit struct. The variant holds no data, so there’s nothing to put in parentheses:

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`

The program behind it:

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));
}

Write the name alone, both in the pattern and where you create the value:

#[derive(Debug)]
enum Status {
Active,
Banned(String),
}
fn label(s: &Status) -> String {
match s {
Status::Active => String::from("active"), // ✅ unit variant: no ()
Status::Banned(reason) => format!("banned ({})", reason),
}
}
fn main() {
println!("{}", label(&Status::Active));
println!("{}", label(&Status::Banned(String::from("spam"))));
let s = Status::Active; // ✅ and no () when you create it either
println!("{:?}", s);
}

Output:

active
banned (spam)
Active
▶ Try it Yourself

If you meant the variant to carry data, change the definition instead, for example Active(u64) for a “since” timestamp, and then Status::Active(_) is the right pattern.

Fix 3: Use braces for a struct with named fields

Section titled “Fix 3: Use braces for a struct with named fields”

Choose this when the message says found struct. A struct with named fields, struct Point { x: i32, y: i32 }, is destructured with braces and field names, not with parentheses:

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 }`

The program behind it:

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);
}

rustc’s suggestion Point { x, y } is exactly right. Use field: name when you want a different variable name:

struct Point {
x: i32,
y: i32,
}
struct Meters(f64); // a tuple struct: here parentheses are right
fn main() {
let p = Point { x: 3, y: 4 };
let Point { x, y } = p; // ✅ braces and the field names
println!("x = {}, y = {}", x, y);
let q = Point { x: -1, y: 7 };
let Point { x: left, y: up } = q; // ✅ rename while destructuring
println!("left = {}, up = {}", left, up);
let Meters(m) = Meters(2.5); // ✅ tuple struct, tuple pattern
println!("{} m", m);
}

Output:

x = 3, y = 4
left = -1, up = 7
2.5 m
▶ Try it Yourself

For an enum variant with named fields, Shape::Rect(w, h) for Rect { w: f64, h: f64 }, the same mistake gives a different code, E0164. The fix is the same: braces.

Fix 4: Use a constant or a match guard instead of a function call

Section titled “Fix 4: Use a constant or a match guard instead of a function call”

Choose this when the message says expected a pattern, found a function call. A pattern must be known at compile time, and a function call isn’t:

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>

The program behind it:

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)));
}

If the value never changes, make it a const; constants can be used inside patterns. If it has to be computed, bind the value to a name and compare in a match guard:

const LIMIT: u32 = 100; // a constant can be used inside a pattern
fn limit_for(premium: bool) -> u32 {
if premium { 500 } else { 100 }
}
fn status(users: Option<u32>) -> &'static str {
match users {
Some(LIMIT) => "full", // ✅ a constant
Some(_) => "open",
None => "closed",
}
}
fn status_for(users: Option<u32>, premium: bool) -> &'static str {
match users {
Some(n) if n >= limit_for(premium) => "full", // ✅ call the function in a guard
Some(_) => "open",
None => "closed",
}
}
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));
}

Output:

full
open
closed
full
open
▶ Try it Yourself

Match guards are explained in Match guards: adding an if.

After a unit variant gets a value. Event::Logout used to be a unit variant, and you changed it to Logout(u64). Every Event::Logout => arm now gives E0532. Fix: Event::Logout(_) =>, or Event::Logout(at) => if you need the value.

Checking only the kind of a value. Coming from Java or TypeScript, you might write if let Shape::Circle = shape to ask “is it a circle?”. Write if let Shape::Circle(_) = shape, or matches!(shape, Shape::Circle(_)) for a quick bool.

Without the Shape:: prefix it’s E0530. If you write a bare name, like Ok => or Circle => after use Shape::*;, rustc reads it as a new variable. It reports E0530, match bindings cannot shadow tuple variants, with the help try specify the pattern arguments: `Ok(..)` . Same fix: add the parentheses.

Quick check

1. For enum Shape { Circle(f64), Empty }, which match arm compiles?

2. rustc says "expected tuple struct or tuple variant, found unit variant Status::Active". What's the fix?

3. struct Point { x: i32, y: i32 }: how do you destructure it with let?

Score: 0 / 3