Zum Inhalt springen

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.)

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

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 Circle ab“ – aber Circle trägt ein f64, also braucht ein korrektes Muster Klammern: Circle(_) oder Circle(..).
  • „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 einem match-Zweig
  • let bindings cannot shadow ...: in let oder if let
  • function 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.

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.

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.14
Quadrat: 4.00
▶ Selbst ausprobieren

.. bedeutet „was auch immer drinsteckt“, und es funktioniert weiter, wenn die Variante später mehr Werte bekommt. Siehe Teile ignorieren mit _ und ...

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 struct

Auf 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 m
Höhe: 1.8 m
gesamt: 5.5 m
▶ Selbst ausprobieren

Dasselbe 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 static

Auf 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 Muster
static 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:

voll
offen
voll
▶ Selbst ausprobieren

Für eine einfache Zahl brauchst du static kaum. const ist die übliche Wahl; siehe Konstanten.

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";.

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