Rust Error E0164: Expected Tuple Struct or Tuple Variant, Found Struct Variant
E0164 means: you wrote parentheses in a pattern, like Shape::Circle(r), after a name that doesn’t take values in parentheses. In today’s Rust you’ll meet it in three situations: an enum variant with named fields (Circle { radius: f64 }) matched as if it were a tuple variant, an associated function like Celsius::new(d) used as a pattern, and an associated constant like Volume::MAX(_) with parentheses after it. Each has a short, clear fix. (This page is part of Rust compiler errors explained.)
The error message
Section titled “The error message”error[E0164]: expected tuple struct or tuple variant, found struct variant `Shape::Circle` --> src/main.rs:8:9 |8 | Shape::Circle(r) => 3.14 * r * r, // ❌ `Circle` has named fields | ^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant |help: the struct variant's field is being ignored |8 - Shape::Circle(r) => 3.14 * r * r, // ❌ `Circle` has named fields8 + Shape::Circle { radius: _ } => 3.14 * r * r, // ❌ `Circle` has named fields |This is the program that produces it:
enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ❌ `Circle` has named fields Shape::Square { side } => side * side, }}
fn main() { println!("{}", area(&Shape::Square { side: 2.0 }));}What it means
Section titled “What it means”The ^^^ covers the whole pattern Shape::Circle(r), and the label says what Rust expected there: “a tuple struct or tuple variant”. Only those two kinds of things are written with parentheses in a pattern, because only they hold values by position, like Some(x) or Meters(m).
Shape::Circle is a struct variant. Its value has a name, radius, and named fields are matched with braces: Shape::Circle { radius }.
Be careful with the help: here. It suggests Shape::Circle { radius: _ }, which fixes the pattern but ignores the radius. Our arm uses r, so copying the suggestion as it is gives a new error, E0425 cannot find value `r` in this scope. When you need the value, give it a name inside the braces, as in Fix 1.
It’s like a form with labelled boxes, “Width: … Height: …”, and you wrote “3, 4” next to the title. The numbers might be right, but the form wants each one in its labelled box.
Why Rust does this
Section titled “Why Rust does this”A pattern has to look like the value it matches. Rust has two ways to hold data, and each has its own pattern (see Enums can hold data):
| Defined as | Created with | Matched with |
|---|---|---|
Circle(f64) (tuple variant) |
Shape::Circle(1.0) |
Shape::Circle(r) |
Circle { radius: f64 } (struct variant) |
Shape::Circle { radius: 1.0 } |
Shape::Circle { radius } |
Named fields are matched by name, not by position, so the order in the pattern doesn’t matter and adding a field later doesn’t silently shift the others. Mixing the two styles is refused, so there’s never a question about which value goes where.
Patterns are also checked at compile time, so they can’t run code. That’s why a function name followed by (d) can’t be a pattern either, even when the function builds exactly the value you’re matching. More in Pattern Matching.
How to fix it
Section titled “How to fix it”Fix 1: Use braces with the field names
Section titled “Fix 1: Use braces with the field names”Choose this when the message says found struct variant, which is the most common E0164. Write the field name (Rust then makes a variable with that name), field: new_name to pick another name, or { .. } to ignore all fields:
enum Shape { Circle { radius: f64 }, Rect { w: f64, h: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ field name in braces Shape::Rect { w: width, h: height } => width * height, // ✅ field: new name }}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle { .. } => "circle", // ✅ "any circle" Shape::Rect { .. } => "rectangle", }}
fn main() { let shapes = [Shape::Circle { radius: 1.0 }, Shape::Rect { w: 2.0, h: 3.0 }]; for shape in &shapes { println!("{}: {:.2}", name(shape), area(shape)); }}Output:
circle: 3.14rectangle: 6.00If you list some fields but not all, add .. at the end, like Shape::Rect { w, .. }. Leaving it out gives E0027, and a misspelled field name gives E0026.
Fix 2: Turn the variant into a tuple variant
Section titled “Fix 2: Turn the variant into a tuple variant”Choose this when parentheses really are what you want: the variant has one obvious value, and you’d rather write Shape::Circle(1.0) everywhere. Change the definition, and the Circle(r) pattern becomes correct:
enum Shape { Circle(f64), // ✅ now a tuple variant: one unnamed value Rect { w: f64, h: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ✅ parentheses fit a tuple variant Shape::Rect { w, h } => w * h, }}
fn main() { let small = Shape::Circle(1.0); // created with parentheses too let big = Shape::Circle(2.0); let door = Shape::Rect { w: 1.0, h: 2.0 }; println!("{:.2} {:.2} {:.2}", area(&small), area(&big), area(&door));}Output:
3.14 12.56 2.00This changes the type, so every place that creates or matches Circle must switch to parentheses too. The compiler lists each one. For two or more values, named fields are usually clearer.
Fix 3: Match the tuple struct itself, and call functions in a guard
Section titled “Fix 3: Match the tuple struct itself, and call functions in a guard”Choose this when the message says found associated function and the label says `fn` calls are not allowed in patterns. You wrote a constructor like Celsius::new(d) where Rust needs a pattern:
error[E0164]: expected tuple struct or tuple variant, found associated function `Celsius::new` --> src/main.rs:11:9 |11 | Celsius::new(d) if d > 25.0 => "warm", // ❌ `new` is a function, not a pattern | ^^^^^^^^^^^^^^^ `fn` calls are not allowed in patternsThe program behind it:
struct Celsius(f64);
impl Celsius { fn new(degrees: f64) -> Celsius { Celsius(degrees) }}
fn feels(t: Celsius) -> &'static str { match t { Celsius::new(d) if d > 25.0 => "warm", // ❌ `new` is a function, not a pattern _ => "cool", }}
fn main() { println!("{}", feels(Celsius::new(30.0)));}Celsius is a tuple struct, so the pattern is the struct’s own name: Celsius(d). Anything that needs a function or method call goes into a match guard (if ... after the pattern):
struct Celsius(f64);
impl Celsius { fn new(degrees: f64) -> Celsius { Celsius(degrees) }
fn is_freezing(&self) -> bool { self.0 <= 0.0 }}
fn feels(t: Celsius) -> &'static str { match t { Celsius(d) if d > 25.0 => "warm", // ✅ the tuple struct itself, plus a guard Celsius(_) => "cool", }}
fn describe(t: &Celsius) -> &'static str { match t { t if t.is_freezing() => "freezing", // ✅ methods go in a guard _ => "not freezing", }}
fn main() { println!("{}", feels(Celsius::new(30.0))); println!("{}", feels(Celsius::new(12.5))); let Celsius(d) = Celsius::new(-3.0); // ✅ also works with `let` println!("{} degrees", d); println!("{}", describe(&Celsius::new(-3.0)));}Output:
warmcool-3 degreesfreezingIf the struct’s field is private (it lives in another module), you can’t write Celsius(d) outside that module. Then use a getter in a guard, like t if t.degrees() > 25.0. See Match guards: adding an if.
Fix 4: Drop the parentheses after a constant
Section titled “Fix 4: Drop the parentheses after a constant”Choose this when the message says found associated constant. A constant is already a complete pattern. It matches one exact value, so there’s nothing to put in parentheses:
error[E0164]: expected tuple struct or tuple variant, found associated constant `Volume::MAX` --> src/main.rs:10:9 |10 | Volume::MAX(_) => "loudest", // ❌ a constant takes no () | ^^^^^^^^^^^^^^ not a tuple struct or tuple variantThe program behind it:
struct Volume;
impl Volume { const MAX: u8 = 10;}
fn label(level: u8) -> &'static str { match level { 0 => "muted", Volume::MAX(_) => "loudest", // ❌ a constant takes no () _ => "normal", }}
fn main() { println!("{}", label(10));}Write the constant on its own:
struct Volume;
impl Volume { const MAX: u8 = 10;}
fn label(level: u8) -> &'static str { match level { 0 => "muted", Volume::MAX => "loudest", // ✅ a constant, on its own 1..=3 => "quiet", _ => "normal", }}
fn main() { for level in [0, 2, 7, 10, u8::MAX] { println!("{}: {}", level, label(level)); }}Output:
0: muted2: quiet7: normal10: loudest255: normalThe same goes for constants from the standard library: u32::MAX(_) is E0164, u32::MAX is a valid pattern.
Where you’ll usually see it
Section titled “Where you’ll usually see it”After switching a variant to named fields. You turned Move(i32, i32) into Move { x: i32, y: i32 } for clarity. Every old Command::Move(x, y) => arm now gives E0164. Fix: Command::Move { x, y } =>.
Matching with a “parser” function. Something like match input { Version::parse(v) => ... }, hoping the function runs while matching. Fix: call it first, then match on the result: match Version::parse(input) { Some(v) => ..., None => ... }.
Free functions, plain structs and unit variants give E0532 instead. The same parentheses mistake is reported as E0532 when the name isn’t reached through a type: a plain function (Some(limit()), expected a pattern, found a function call), a struct with named fields (let Point(x, y) = p;, found struct `Point` ), or a unit variant (Status::Active()). The fixes are the same as on this page.
Related errors
Section titled “Related errors”- E0532: expected tuple struct or tuple variant, found unit variant or struct: the same mix-up for plain structs, unit variants and free functions, and the reverse (a tuple variant written without parentheses).
- E0533: expected unit struct, unit variant or constant, found struct variant: a struct variant written with no braces at all, like
Shape::Circle =>. - E0026: struct or variant does not have a field named x: the braces are right, but a field name inside is wrong.
- E0027: pattern does not mention field x: braces that leave fields out; add
... - E0425: cannot find value in this scope: what you get if you copy the
{ radius: _ }suggestion but still user. - All compiler errors explained
Quick check
Section titled “Quick check”Quick check
1. For enum Shape { Circle { radius: f64 } }, which arm uses the radius correctly?
2. Celsius::new(d) => ... gives "fn calls are not allowed in patterns". Celsius is struct Celsius(f64);. What pattern works?
3. How do you match the associated constant Volume::MAX?
Score: 0 / 3
Read more
Section titled “Read more”- E0164 — Rust error codes index: the official explanation, with the associated-constant example.
- Pattern Syntax — The Rust Book: destructuring enums with braces or parentheses, ignoring fields with
.., and match guards. - Destructuring enums — Rust by Example: tuple and struct variants matched side by side.
- Patterns — The Rust Reference: which paths may appear in tuple struct patterns and struct patterns.