Skip to content

Rust Error E0533: Expected Unit Struct, Unit Variant or Constant, Found Struct Variant

E0533 means: you wrote a name like Shape::Circle on its own, but that name needs more than its name to be used there. Most often it’s an enum variant with named fields (Circle { radius: f64 }) written without its { }, either in a match arm or when creating a value. Less often it’s a function or method written where only a fixed value can go. Both are quick to fix once you know what rustc is asking for. (This page is part of Rust compiler errors explained.)

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
| +++++++++++++

This is the program that produces it:

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

The ^^^ points at Shape::Circle, and the headline explains what was allowed there: a pattern that is just a name 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 MAX: u32 = 100;

Shape::Circle is none of those. It’s a struct variant: it carries a radius. A bare Shape::Circle would match “a circle”, but say nothing about its field, and Rust wants the shape of the pattern to match the shape of the variant. The help: line shows the fix: add the braces.

The second kind of E0533 says expected value, found struct variant. Same mix-up, but when creating a value, usually written with parentheses like Shape::Circle(2.0).

It’s like a parcel form with a box that says “Size: S, M or L”, and you wrote “Custom”. Custom is a real option, but it needs the measurements filled in next to it.

Enum variants come in three shapes, and each one is written its own way, both when you create it and when you match on it (see Enums can hold data):

Variant Create it Match it
Unit: Empty Shape::Empty Shape::Empty
Tuple: Point(f64, f64) Shape::Point(1.0, 2.0) Shape::Point(x, y) or Shape::Point(..)
Struct: Circle { radius: f64 } Shape::Circle { radius: 2.0 } Shape::Circle { radius } or Shape::Circle { .. }

Keeping the shapes strict means a pattern always looks like the thing it matches, so you can read a match and know exactly what data each arm has. It also means that when a variant changes shape, for example when Empty gains a field, every place that uses the old shape is flagged instead of silently doing the wrong thing.

Fix 1: Add { .. } or the fields to the pattern

Section titled “Fix 1: Add { .. } or the fields to the pattern”

Choose this when the error points at a match, if let or matches! arm and says found struct variant. Write { .. } if you don’t need the fields, or name them if you do. rustc’s suggestion { radius: _ } also works, and { .. } is the shorter way to say the same thing.

enum Shape {
Circle { radius: f64 },
Square { side: f64 },
Empty,
}
fn name(shape: &Shape) -> &'static str {
match shape {
Shape::Circle { .. } => "circle", // ✅ "a circle, whatever its radius"
Shape::Square { .. } => "square",
Shape::Empty => "nothing", // a unit variant: no braces needed
}
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle { radius } => 3.14 * radius * radius, // ✅ fields named because we need them
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!("{} circle(s)", circles);
}

Output:

circle: 3.14
square: 9.00
nothing: 0.00
1 circle(s)
▶ Try it Yourself

{ .. } works for every struct variant, however many fields it has. For tuple variants the same idea is written (..). See Ignoring parts with _ and ...

Fix 2: Create the value with braces and field names

Section titled “Fix 2: Create the value with braces and field names”

Choose this when the message says expected value, found struct variant. You’re creating a struct variant as if it were a tuple variant (or with no fields at all):

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 field
8 + let shape = Shape::Circle { radius: /* value */ }; // ❌ `Circle` has a named field
|

The program behind it:

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

The /* value */ in the suggestion is a placeholder for your value. Fields of a struct variant are set by name, inside braces:

#[derive(Debug)]
enum Shape {
Circle { radius: f64 },
Square { side: f64 },
}
impl Shape {
// a short constructor, if you want to write `Shape::circle(2.0)`
fn circle(radius: f64) -> Shape {
Shape::Circle { radius }
}
}
fn main() {
let a = Shape::Circle { radius: 2.0 }; // ✅ braces and the field name
let b = Shape::Square { side: 1.5 };
let c = Shape::circle(0.5);
println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
}

Output:

Circle { radius: 2.0 }
Square { side: 1.5 }
Circle { radius: 0.5 }
▶ Try it Yourself

If you’d rather write Shape::Circle(2.0), change the definition to a tuple variant: Circle(f64). That’s a fine choice for one obvious field; named fields are clearer when there are several.

Fix 3: Use a constant or a match guard instead of a function

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

Choose this when the message says found associated function. It appears for methods too, like String::len. A pattern must be a value that’s known at compile time. A function call isn’t, so a function’s name can’t be used as a pattern:

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 constant

The program behind it:

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

If the value never changes, make it a const. Constants can be patterns. If it has to be computed, keep the function and compare in a match guard with if:

struct Limits;
impl Limits {
const MAX_USERS: u32 = 100; // a constant can be used as a pattern
fn max_rooms(premium: bool) -> u32 {
if premium { 20 } else { 5 }
}
}
fn status(users: u32) -> &'static str {
match users {
0 => "empty",
Limits::MAX_USERS => "full", // ✅ a constant
_ => "open",
}
}
fn rooms_status(rooms: u32, premium: bool) -> &'static str {
match rooms {
n if n >= Limits::max_rooms(premium) => "no more rooms", // ✅ call it in a guard
_ => "you can add a room",
}
}
fn main() {
println!("{}", status(0));
println!("{}", status(100));
println!("{}", status(42));
println!("{}", rooms_status(5, false));
println!("{}", rooms_status(5, true));
}

Output:

empty
full
open
no more rooms
you can add a room
▶ Try it Yourself

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

After a unit variant gets fields. Status::Done used to be a unit variant, and you changed it to Done { at: u64 }. Every Status::Done => arm and every let s = Status::Done; now gives E0533. Fix: Status::Done { .. } => in patterns, Status::Done { at: 0 } (with a real value) where you create it.

Coming from another language. In Java or TypeScript you might write case Circle: to check only the kind of a value. In Rust, write Shape::Circle { .. } =>, or matches!(shape, Shape::Circle { .. }) for a quick bool.

The tuple-variant version. For a tuple variant like Circle(f64), a bare Shape::Circle => arm gives a different code, E0532, with the same headline “expected unit struct, unit variant or constant, found tuple variant Shape::Circle”. The fix is Shape::Circle(_) or Shape::Circle(..). And parentheses on a struct variant in a pattern, like Shape::Circle(r) => for Circle { radius: f64 }, gives E0164, “expected tuple struct or tuple variant, found struct variant”. Fix: Shape::Circle { radius: r } =>.

Quick check

1. For enum Shape { Circle { radius: f64 } }, which match arm compiles?

2. let s = Shape::Circle(2.0); gives "expected value, found struct variant". What's the fix?

3. Which of these can be used on its own as a match pattern?

Score: 0 / 3