Rust-Fehler E0530: match bindings cannot shadow tuple variants (Variantenname)
E0530 bedeutet: Ein Name in deinem Muster ist schon vergeben. Du hast einen einfachen Namen wie Circle geschrieben, an einer Stelle, an der Rust normalerweise eine neue Variable anlegt. Aber Circle bedeutet in diesem Gültigkeitsbereich (Scope) schon etwas anderes: eine Tupel-Variante, ein Tupel-Struct oder ein static. Rust weigert sich, das still hinter einer neuen Variable zu verstecken, denn das wäre fast nie das, was du meinst. Der klassische Fall ist ein match-Zweig Circle => nach use Shape::*;, und die Lösung sind meistens zwei Zeichen: Circle(..). (Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.)
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“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` trägt einen Wert | ^^^^^^ | | | cannot be named the same as a tuple variant | help: try specify the pattern arguments: `Circle(..)`Auf Deutsch: „Bindungen in einem match können Tupel-Varianten nicht verdecken.“ Die Hinweise sagen: „Die Tupel-Variante Circle wird hier importiert“, „darf nicht so heißen wie eine Tupel-Variante“ und „Gib die Argumente des Musters an: Circle(..)“.
Dieses Programm erzeugt den Fehler:
enum Shape { Circle(f64), Square(f64),}
use Shape::*;
fn name(shape: &Shape) -> &'static str { match shape { Circle => "circle", // ❌ `Circle` trägt einen Wert Square(_) => "square", }}
fn main() { println!("{}", name(&Circle(1.0)));}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Die ^^^ zeigen in Zeile 10 auf Circle, und die --- in Zeile 6 zeigen, woher dieser Name kommt: use Shape::*; hat die Variante Shape::Circle in den Scope geholt.
In einem Muster legt ein einfacher Name wie x oder other eine neue Variable an, die auf alles passt. Circle => könnte also zweierlei bedeuten:
- „Gleiche die Variante
Circleab“ – aberCircleträgt einf64, also braucht ein korrektes Muster Klammern:Circle(_)oderCircle(..). - „Passe auf alles und nenne es
Circle“ – eine neue Variable, die die Variante verdecken würde.
Rust rät nicht. Die Überschrift sagt dir, mit welcher Art von Namen du kollidiert bist, und das erste Wort sagt dir, wo:
match bindings cannot shadow ...: in einemmatch-Zweiglet bindings cannot shadow ...: inletoderif letfunction parameters cannot shadow ...: in der Parameterliste einer Funktion
Am Ende steht tuple variants (Tupel-Varianten), tuple structs (Tupel-Structs) oder statics (Statics).
Das ist, als würdest du deinen Hund „Doktor“ nennen. Jedes Mal, wenn im Wartezimmer jemand „Doktor!“ ruft, weiß keiner, wer gemeint ist.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“Ohne diese Regel wäre Circle => eine neue Variable namens Circle. Sie würde auf jeden Wert passen, und jeder Zweig danach wäre toter Code. Dein Programm würde kompilieren und dann auch für Quadrate „circle“ ausgeben. Das ist ein fieser Bug, der sich hinter Code versteckt, der richtig aussieht.
Deshalb macht Rust daraus einen Fehler, sobald eine neue Variable den Namen einer Tupel-Variante, eines Tupel-Structs oder eines Statics bekommen würde. Entweder sagst du mit Klammern, was du meinst, oder du wählst einen anderen Namen. Unit-Varianten wie None und Konstanten (const) sind anders: Sie sind für sich allein gültige Muster, also liest Rust sie als „gleiche diesen Wert ab“. Siehe Pattern Matching und Enums.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: (..) oder (_) ergänzen, um die Variante abzugleichen
Abschnitt betitelt „Lösung 1: (..) oder (_) ergänzen, um die Variante abzugleichen“Nimm diese Lösung, wenn in der Meldung tuple variants oder tuple structs steht – das ist der häufigste Fall. Du meintest die Variante, also gib ihr ihre Klammern, so wie es die Hilfe von rustc vorschlägt. Der volle Pfad, Shape::Circle(_), ist sogar noch klarer:
enum Shape { Circle(f64), Square(f64),}
use Shape::*;
fn name(shape: &Shape) -> &'static str { match shape { Circle(..) => "Kreis", // ✅ die Variante, egal welcher Wert drinsteckt Square(_) => "Quadrat", }}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ✅ voller Pfad, und der Wert wird benutzt 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)); }}Ausgabe:
Kreis: 3.14Quadrat: 4.00.. bedeutet „was auch immer drinsteckt“, und es funktioniert weiter, wenn die Variante später mehr Werte bekommt. Siehe Teile ignorieren mit _ und ...
Lösung 2: Die Variable umbenennen
Abschnitt betitelt „Lösung 2: Die Variable umbenennen“Nimm diese Lösung, wenn du wirklich eine neue Variable wolltest und ihr Name nur zufällig zu einem Typ passt. Das passiert oft bei let und bei Funktionsparametern, wenn du eine Variable nach ihrem Typ benennst:
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` ist ein Tupel-Struct | ^^^^^^ cannot be named the same as a tuple structAuf Deutsch: „let-Bindungen können Tupel-Structs nicht verdecken.“ Meters ist in Zeile 1 als Tupel-Struct definiert, und die Variable darf nicht genauso heißen.
Das Programm dahinter:
struct Meters(f64);
fn main() { let Meters = 5.0; // ❌ `Meters` ist ein Tupel-Struct println!("{}", Meters);}Die Namenskonventionen von Rust lösen das für dich: Typen und Varianten schreibt man in CamelCase, Variablen in snake_case. Nimm einen kleingeschriebenen Namen, und die Kollision ist weg:
struct Meters(f64);
fn total(meters: &[Meters]) -> f64 { meters.iter().map(|m| m.0).sum()}
fn main() { let meters = 5.0; // ✅ ein kleingeschriebener Variablenname println!("{} m", meters);
let Meters(height) = Meters(1.8); // ✅ oder das Tupel-Struct destrukturieren println!("Höhe: {} m", height);
println!("gesamt: {} m", total(&[Meters(2.0), Meters(3.5)]));}Ausgabe:
5 mHöhe: 1.8 mgesamt: 5.5 mDasselbe gilt für einen Parameter: fn show(Point: i32) ergibt function parameters cannot shadow tuple structs, und fn show(point: i32) behebt es. Siehe Regeln für Namen.
Lösung 3: Ein const (oder einen Match Guard) statt eines static benutzen
Abschnitt betitelt „Lösung 3: Ein const (oder einen Match Guard) statt eines static benutzen“Nimm diese Lösung, wenn in der Meldung statics steht. Wahrscheinlich wolltest du mit einem festen Wert vergleichen. Ein static kann kein Muster sein, ein const schon:
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", // ❌ ein Static kann kein Muster sein | ^^^^^ cannot be named the same as a staticAuf Deutsch: „Bindungen in einem match können Statics nicht verdecken.“ Rust liest LIMIT hier als neue Variable und lehnt das ab, weil es schon ein static mit diesem Namen gibt.
Das Programm dahinter:
static LIMIT: u32 = 100;
fn status(users: u32) -> &'static str { match users { LIMIT => "full", // ❌ ein Static kann kein Muster sein _ => "open", }}
fn main() { println!("{}", status(100));}Mach aus static ein const. Muss es ein static bleiben (zum Beispiel, weil anderer Code seine Adresse benutzt), dann binde den Wert an einen Namen und vergleiche in einem Match Guard:
const LIMIT: u32 = 100; // ✅ ein const funktioniert als Musterstatic MAX_USERS: u32 = 500; // ein Static bleibt ein Static
fn status(users: u32) -> &'static str { match users { LIMIT => "voll", _ => "offen", }}
fn premium_status(users: u32) -> &'static str { match users { n if n >= MAX_USERS => "voll", // ✅ ein Static im Guard vergleichen _ => "offen", }}
fn main() { println!("{}", status(100)); println!("{}", status(42)); println!("{}", premium_status(500));}Ausgabe:
volloffenvollFür eine einfache Zahl brauchst du static kaum. const ist die übliche Wahl; siehe Konstanten.
Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“Ok => oder Some => ohne Klammern. Ok, Err und Some sind Tupel-Varianten aus dem Prelude, also ergibt match result { Ok => ... } den Fehler E0530 mit der Hilfe try specify the pattern arguments: `Ok(..)` . Lösung: Ok(_) => oder Ok(value) =>.
In if let. if let Some(Some) = x versucht, den inneren Wert Some zu nennen, und ergibt let bindings cannot shadow tuple variants. Lösung: ein kleingeschriebener Name, if let Some(inner) = x.
Mit dem vollen Pfad ist es stattdessen E0532. Shape::Circle => kann keine neue Variable sein (ein Variablenname hat kein ::), also meldet rustc E0532, expected unit struct, unit variant or constant, found tuple variant. Gleiche Lösung: (_) oder (..) ergänzen.
Ein let mit dem Namen eines Unit-Structs ist E0308. Mit struct Guest; legt die Zeile let Guest = "Ana"; gar keine Variable an: rustc liest Guest als das Unit-Struct und meldet E0308 (mismatched types, Typen passen nicht), mit dem Hinweis `Guest` is interpreted as a unit struct, not a new binding („Guest wird als Unit-Struct gelesen, nicht als neue Bindung“). Lösung: Benenn die Variable um, let guest = "Ana";.
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0532: expected unit struct, unit variant or constant, found tuple variant: derselbe Fehler mit einem Pfad geschrieben, etwa
Shape::Circle =>. - E0533: expected unit struct, unit variant or constant, found struct variant: eine Variante mit benannten Feldern, ohne
{ .. }benutzt. - E0004: non-exhaustive patterns: Auch nachdem du die Zweige behoben hast, muss das
matchjede Variante abdecken. - E0308: mismatched types: das, was ein
letmit dem Namen eines Unit-Structs ergibt. - E0425: cannot find value in this scope: das umgekehrte Problem – ein Name, den es gar nicht gibt.
- Alle Compilerfehler: die vollständige Liste der Fehlerseiten.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Nach use Shape::*;, wobei Circle(f64) eine Variante ist: Welcher Match-Zweig kompiliert?
2. rustc meldet „let bindings cannot shadow tuple structs“ für let Meters = 5.0;. Was ist die einfachste Lösung?
3. static LIMIT: u32 = 100; kann kein Match-Muster sein. Was geht stattdessen?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0530 – Rust error codes index (auf Englisch): die offizielle Erklärung, mit dem Fall der fehlenden
(_)und dem Fallstaticgegenconst. - Mustersyntax – Das Rust-Buch: benannte Variablen abgleichen, Enums destrukturieren und Werte mit
_und..ignorieren. - Identifier patterns – The Rust Reference (auf Englisch): die genaue Regel, wann ein Name in einem Muster eine neue Variable ist und wann er auf etwas Vorhandenes verweist.
- Destructuring enums – Rust by Example (auf Englisch): Unit- und Tupel-Varianten direkt nebeneinander abgleichen.
- Static items – The Rust Reference (auf Englisch): wie sich ein
staticvon einemconstunterscheidet (ein fester Platz im Speicher, kein Wert, der an jede Stelle kopiert wird).