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.)
The error message
Section titled “The error message”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 }));}What it means
Section titled “What it means”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::EmptyorNone - 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.
Why Rust does this
Section titled “Why Rust does this”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.
How to fix it
Section titled “How to fix it”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.14square: 9.00nothing: 0.001 circle(s){ .. } 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 field8 + 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 }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 constantThe 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:
emptyfullopenno more roomsyou can add a roomMatch guards are explained in Match guards: adding an if.
Where you’ll usually see it
Section titled “Where you’ll usually see it”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 } =>.
Related errors
Section titled “Related errors”- E0559: variant has no field named x: the braces are right, but a field name inside them is wrong.
- E0026: struct or variant does not have a field named x: a wrong field name inside a pattern’s braces.
- E0027: pattern does not mention field x: braces in a pattern that leave fields out; add
... - E0004: non-exhaustive patterns: after fixing the arms, the
matchstill has to cover every variant. E0532: expected unit struct, unit variant or constant, found tuple variant: the tuple-variant version (see above).- All compiler errors explained
Quick check
Section titled “Quick check”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
Read more
Section titled “Read more”- E0533 — Rust error codes index: the official explanation of this error.
- Pattern Syntax — The Rust Book: destructuring enums, ignoring values with
.., and match guards. - Destructuring enums — Rust by Example: matching unit, tuple and struct variants side by side.
- E0532 — Rust error codes index: the official page for the tuple-variant version of this mistake.
- Patterns — The Rust Reference: which paths are allowed as patterns, and the struct and tuple-struct pattern rules.