Rust Error E0530: Match Bindings Cannot Shadow Tuple Variants
E0530 means: a name in your pattern is already taken. You wrote a plain name, like Circle, where Rust would normally create a new variable. But Circle already means something else in this scope: a tuple variant, a tuple struct, or a static. Rust refuses to quietly hide it behind a new variable, because that would almost never be what you meant. The classic case is a match arm Circle => after use Shape::*;, and the fix is usually two characters: Circle(..). (This page is part of Rust compiler errors explained.)
The error message
Section titled “The error message”error[E0530]: match bindings cannot shadow tuple variants --> src/main.rs:10:9 | 6 | use Shape::*; | -------- the tuple variant `Circle` is imported here...10 | Circle => "circle", // ❌ `Circle` holds a value | ^^^^^^ | | | cannot be named the same as a tuple variant | help: try specify the pattern arguments: `Circle(..)`This is the program that produces it:
enum Shape { Circle(f64), Square(f64),}
use Shape::*;
fn name(shape: &Shape) -> &'static str { match shape { Circle => "circle", // ❌ `Circle` holds a value Square(_) => "square", }}
fn main() { println!("{}", name(&Circle(1.0)));}What it means
Section titled “What it means”The ^^^ points at Circle on line 10, and the --- on line 6 shows where that name comes from: use Shape::*; brought the variant Shape::Circle into scope.
In a pattern, a plain lowercase-looking name like x or other creates a new variable that matches anything. So Circle => could mean two things:
- “match the variant
Circle”, butCircleholds anf64, so a correct pattern needs parentheses:Circle(_)orCircle(..). - “match anything and call it
Circle”, a new variable that would hide the variant.
Rust won’t guess. The headline tells you what kind of name you collided with, and the first word tells you where:
match bindings cannot shadow ...: in amatcharmlet bindings cannot shadow ...: inletorif letfunction parameters cannot shadow ...: in a function’s parameter list
and it ends in tuple variants, tuple structs or statics.
It’s like naming your dog “Doctor”. Every time someone shouts “Doctor!” in the waiting room, nobody knows who’s meant.
Why Rust does this
Section titled “Why Rust does this”Without this rule, Circle => would be a new variable named Circle. It would match every value, and every arm after it would be dead code. Your program would compile, then print “circle” for squares too. That’s a nasty bug that hides behind code that looks right.
So Rust makes it an error whenever a new variable would take the name of a tuple variant, a tuple struct or a static. You either say what you mean with parentheses, or pick another name. Unit variants like None and constants (const) are different: those are valid patterns on their own, so Rust reads them as “match this value”. See Pattern matching and Enums.
How to fix it
Section titled “How to fix it”Fix 1: Add (..) or (_) to match the variant
Section titled “Fix 1: Add (..) or (_) to match the variant”Choose this when the message says tuple variants or tuple structs, which is the most common case. You meant the variant, so give it its parentheses, as rustc’s help suggests. Writing the full path, Shape::Circle(_), is even clearer:
enum Shape { Circle(f64), Square(f64),}
use Shape::*;
fn name(shape: &Shape) -> &'static str { match shape { Circle(..) => "circle", // ✅ the variant, any value inside Square(_) => "square", }}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ✅ full path, and use the value Shape::Square(side) => side * side, }}
fn main() { let shapes = [Circle(1.0), Square(2.0)]; for shape in &shapes { println!("{}: {:.2}", name(shape), area(shape)); }}Output:
circle: 3.14square: 4.00.. means “whatever is inside”, and it keeps working if the variant gets more values later. See Ignoring parts with _ and ...
Fix 2: Rename the variable
Section titled “Fix 2: Rename the variable”Choose this when you really wanted a new variable, and its name just happens to match a type. That often happens with let and function parameters, when you name a variable after its type:
error[E0530]: let bindings cannot shadow tuple structs --> src/main.rs:4:9 |1 | struct Meters(f64); | ------------------- the tuple struct `Meters` is defined here...4 | let Meters = 5.0; // ❌ `Meters` is a tuple struct | ^^^^^^ cannot be named the same as a tuple structThe program behind it:
struct Meters(f64);
fn main() { let Meters = 5.0; // ❌ `Meters` is a tuple struct println!("{}", Meters);}Rust’s naming style solves this for you: types and variants are CamelCase, variables are snake_case. Use a lowercase name and the clash is gone:
struct Meters(f64);
fn total(meters: &[Meters]) -> f64 { meters.iter().map(|m| m.0).sum()}
fn main() { let meters = 5.0; // ✅ a lowercase variable name println!("{} m", meters);
let Meters(height) = Meters(1.8); // ✅ or destructure the tuple struct println!("height: {} m", height);
println!("total: {} m", total(&[Meters(2.0), Meters(3.5)]));}Output:
5 mheight: 1.8 mtotal: 5.5 mThe same goes for a parameter: fn show(Point: i32) gives function parameters cannot shadow tuple structs, and fn show(point: i32) fixes it. See Naming rules.
Fix 3: Use a const (or a match guard) instead of a static
Section titled “Fix 3: Use a const (or a match guard) instead of a static”Choose this when the message says statics. You probably wanted to compare against a fixed value. A static can’t be used as a pattern, but a const can:
error[E0530]: match bindings cannot shadow statics --> src/main.rs:5:9 |1 | static LIMIT: u32 = 100; | ------------------------ the static `LIMIT` is defined here...5 | LIMIT => "full", // ❌ a static can't be a pattern | ^^^^^ cannot be named the same as a staticThe program behind it:
static LIMIT: u32 = 100;
fn status(users: u32) -> &'static str { match users { LIMIT => "full", // ❌ a static can't be a pattern _ => "open", }}
fn main() { println!("{}", status(100));}Change static to const. If it has to stay a static (for example, because other code takes its address), bind the value to a name and compare in a match guard:
const LIMIT: u32 = 100; // ✅ a const works as a patternstatic MAX_USERS: u32 = 500; // a static stays a static
fn status(users: u32) -> &'static str { match users { LIMIT => "full", _ => "open", }}
fn premium_status(users: u32) -> &'static str { match users { n if n >= MAX_USERS => "full", // ✅ compare a static in a guard _ => "open", }}
fn main() { println!("{}", status(100)); println!("{}", status(42)); println!("{}", premium_status(500));}Output:
fullopenfullFor a plain number you’d rarely need static at all. const is the usual choice; see Constants.
Where you’ll usually see it
Section titled “Where you’ll usually see it”Ok => or Some => without parentheses. Ok, Err and Some are tuple variants from the prelude, so match result { Ok => ... } gives E0530 with the help try specify the pattern arguments: `Ok(..)` . Fix: Ok(_) => or Ok(value) =>.
Inside if let. if let Some(Some) = x tries to call the inner value Some and gives let bindings cannot shadow tuple variants. Fix: a lowercase name, if let Some(inner) = x.
With the full path, it’s E0532 instead. Shape::Circle => can’t be a new variable (a variable name has no ::), so rustc reports E0532, expected unit struct, unit variant or constant, found tuple variant. Same fix: add (_) or (..).
A let with the name of a unit struct is E0308. With struct Guest;, the line let Guest = "Ana"; doesn’t create a variable at all: rustc reads Guest as the unit struct and reports E0308 (mismatched types), saying `Guest` is interpreted as a unit struct, not a new binding. Fix: rename the variable, let guest = "Ana";.
Related errors
Section titled “Related errors”- E0532: expected unit struct, unit variant or constant, found tuple variant: the same mistake written with a path, like
Shape::Circle =>. - E0533: expected unit struct, unit variant or constant, found struct variant: a variant with named fields used without
{ .. }. - E0004: non-exhaustive patterns: after you fix the arms, the
matchstill has to cover every variant. - E0308: mismatched types: what a
letwith a unit struct’s name gives. - E0425: cannot find value in this scope: the opposite problem, a name that doesn’t exist at all.
- All compiler errors explained
Quick check
Section titled “Quick check”Quick check
1. After use Shape::*;, where Circle(f64) is a variant, which match arm compiles?
2. rustc says "let bindings cannot shadow tuple structs" for let Meters = 5.0;. What's the simplest fix?
3. static LIMIT: u32 = 100; can't be used as a match pattern. What can?
Score: 0 / 3
Read more
Section titled “Read more”- E0530 — Rust error codes index: the official explanation, with the missing
(_)case and thestaticvsconstcase. - Pattern Syntax — The Rust Book: matching named variables, destructuring enums, and ignoring values with
_and... - Identifier patterns — The Rust Reference: the exact rule for when a name in a pattern is a new variable and when it refers to something that exists.
- Destructuring enums — Rust by Example: matching unit and tuple variants side by side.
- Static items — The Rust Reference: how a
staticdiffers from aconst(one fixed place in memory, not a value copied into each use).