Rust-Fehler E0532: expected unit struct, unit variant or constant, found tuple variant
E0532 bedeutet: Die Form deines Musters passt nicht zur Form dessen, was du genannt hast. Der klassische Fall ist ein match-Zweig wie Shape::Circle => für eine Variante, die Daten enthält, nämlich Circle(f64). Rust will die Klammern sehen: Shape::Circle(_). Der umgekehrte Fehler bekommt denselben Code, nur mit der anderen Meldung „expected tuple struct or tuple variant“: Klammern an etwas, das gar keine Daten in Klammern hat, wie Status::Active(). Beides behebst du mit einer Zeile. (Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.)
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“error[E0532]: expected unit struct, unit variant or constant, found tuple variant `Shape::Circle` --> src/main.rs:8:9 |2 | Circle(f64), | ----------- `Shape::Circle` defined here...8 | Shape::Circle => "circle", // ❌ `Circle` enthält einen Wert | ^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `Shape::Circle(_)`Auf Deutsch: „Unit-Struct, Unit-Variante oder Konstante erwartet, Tupel-Variante Shape::Circle gefunden.“ Die Hilfe sagt: „Benutze stattdessen die Mustersyntax für Tupel-Varianten: Shape::Circle(_).“
Dieses Programm erzeugt den Fehler:
enum Shape { Circle(f64), Square(f64),}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle => "circle", // ❌ `Circle` enthält einen Wert Shape::Square(_) => "square", }}
fn main() { println!("{}", name(&Shape::Circle(1.0)));}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Die ^^^ zeigen in Zeile 8 auf Shape::Circle, und die --- in Zeile 2 zeigen, wie die Variante definiert ist: Circle(f64), eine Tupel-Variante, die ein f64 mitträgt. Ein Muster, das nur aus einem Namen besteht, ohne irgendetwas dahinter, muss eins von drei Dingen sein:
- ein Unit-Struct, etwa
struct Empty; - eine Unit-Variante, also eine Variante ohne Daten, etwa
Shape::EmptyoderNone - eine Konstante, etwa
const LIMIT: u32 = 100;
Shape::Circle ist nichts davon. Die Hilfe-Zeile liefert die Lösung gleich mit: Shape::Circle(_), also „ein Kreis, egal mit welchem Wert“.
Die zweite Überschrift von E0532 ist das Spiegelbild: expected tuple struct or tuple variant, found unit variant `Status::Active` (oder found struct, oder found constant). Da hast du Klammern hinter einen Namen geschrieben, und das Benannte nimmt keine Werte in Klammern an.
Das ist wie ein Formular, auf dem steht: „Haustier: Hund (Name: ____)“. Schreibst du nur „Hund“, bleibt das Namensfeld leer. Und schreibst du „Fisch (Name: Blubb)“, wo das Formular nur „Fisch“ ohne Feld vorsieht, erfindest du ein Feld, das es nicht gibt.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“Jedes Struct und jede Enum-Variante hat eine von drei Formen. Du schreibst sie beim Erzeugen genauso wie beim Abgleichen (siehe Enums können Daten enthalten):
| Art | Erzeugen | Abgleichen |
|---|---|---|
Unit: Empty |
Shape::Empty |
Shape::Empty |
Tupel: Circle(f64) |
Shape::Circle(1.0) |
Shape::Circle(r) oder Shape::Circle(..) |
Struct: Rect { w: f64, h: f64 } |
Shape::Rect { w: 2.0, h: 3.0 } |
Shape::Rect { w, h } oder Shape::Rect { .. } |
Weil die Formen streng sind, sieht ein Muster immer aus wie der Wert, den es abgleicht. Du kannst ein match lesen und siehst sofort, welche Daten jeder Zweig hat. Das hilft auch, wenn du einen Typ änderst: Bekommt Empty später einen Wert und wird zu Empty(u32), meldet Rust jeden alten Shape::Empty-Zweig, statt still etwas Neues abzugleichen.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: (_), (..) oder Namen für die Werte ergänzen
Abschnitt betitelt „Lösung 1: (_), (..) oder Namen für die Werte ergänzen“Nimm diese Lösung, wenn die Meldung found tuple variant oder found tuple struct sagt. Das ist das häufigste E0532. Nimm _ für jeden Wert, den du nicht brauchst, .., um alle auf einmal zu überspringen, oder einen Namen, wenn du den Wert benutzen willst:
enum Shape { Circle(f64), Rect(f64, f64), Empty,}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle(_) => "Kreis", // ✅ ein Feld, ignoriert Shape::Rect(..) => "Rechteck", // ✅ beliebig viele Felder, alle ignoriert Shape::Empty => "nichts", // eine Unit-Variante: keine Klammern }}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ✅ das Feld binden, weil wir es brauchen Shape::Rect(w, h) => w * h, Shape::Empty => 0.0, }}
fn main() { let shapes = [Shape::Circle(1.0), Shape::Rect(2.0, 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!("{} Kreis(e)", circles);}Ausgabe:
Kreis: 3.14Rechteck: 6.00nichts: 0.001 Kreis(e)(..) ist praktisch für Varianten mit mehreren Werten, und es funktioniert weiter, wenn du später noch einen hinzufügst. Siehe Teile ignorieren mit _ und ...
Lösung 2: Die () bei einer Unit-Variante entfernen
Abschnitt betitelt „Lösung 2: Die () bei einer Unit-Variante entfernen“Nimm diese Lösung, wenn die Meldung found unit variant oder found unit struct sagt. Die Variante enthält keine Daten, also gibt es nichts, was in die Klammern gehört:
error[E0532]: expected tuple struct or tuple variant, found unit variant `Status::Active` --> src/main.rs:8:9 |2 | Active, | ------ `Status::Active` defined here...8 | Status::Active() => "active", // ❌ `Active` enthält keine Daten | ^^^^^^^^^^^^^^^^ help: use this syntax instead: `Status::Active`Die Hilfe sagt: „Benutze stattdessen diese Syntax: Status::Active“, also den Namen ohne Klammern.
Das Programm dazu:
enum Status { Active, Banned(String),}
fn label(s: &Status) -> &'static str { match s { Status::Active() => "active", // ❌ `Active` enthält keine Daten Status::Banned(_) => "banned", }}
fn main() { println!("{}", label(&Status::Active));}Schreib den Namen allein, sowohl im Muster als auch dort, wo du den Wert erzeugst:
#[derive(Debug)]enum Status { Active, Banned(String),}
fn label(s: &Status) -> String { match s { Status::Active => String::from("aktiv"), // ✅ Unit-Variante: keine () Status::Banned(reason) => format!("gesperrt ({})", reason), }}
fn main() { println!("{}", label(&Status::Active)); println!("{}", label(&Status::Banned(String::from("Spam")))); let s = Status::Active; // ✅ und auch beim Erzeugen keine () println!("{:?}", s);}Ausgabe:
aktivgesperrt (Spam)ActiveWolltest du eigentlich, dass die Variante Daten mitträgt, dann ändere stattdessen die Definition, zum Beispiel Active(u64) für einen Zeitstempel „aktiv seit“. Dann ist Status::Active(_) das richtige Muster.
Lösung 3: Geschweifte Klammern für ein Struct mit benannten Feldern
Abschnitt betitelt „Lösung 3: Geschweifte Klammern für ein Struct mit benannten Feldern“Nimm diese Lösung, wenn die Meldung found struct sagt. Ein Struct mit benannten Feldern wie struct Point { x: i32, y: i32 } zerlegst du mit geschweiften Klammern und den Feldnamen, nicht mit runden Klammern:
error[E0532]: expected tuple struct or tuple variant, found struct `Point` --> src/main.rs:8:9 |1 | / struct Point {2 | | x: i32,3 | | y: i32,4 | | } | |_- `Point` defined here...8 | let Point(x, y) = p; // ❌ `Point` hat benannte Felder | ^^^^^^^^^^^ help: use struct pattern syntax instead: `Point { x, y }`Das Programm dazu:
struct Point { x: i32, y: i32,}
fn main() { let p = Point { x: 3, y: 4 }; let Point(x, y) = p; // ❌ `Point` hat benannte Felder println!("{} {}", x, y);}Der Vorschlag von rustc, Point { x, y }, ist genau richtig. Mit feld: name gibst du der Variable einen anderen Namen:
struct Point { x: i32, y: i32,}
struct Meters(f64); // ein Tupel-Struct: hier sind runde Klammern richtig
fn main() { let p = Point { x: 3, y: 4 }; let Point { x, y } = p; // ✅ geschweifte Klammern und die Feldnamen println!("x = {}, y = {}", x, y);
let q = Point { x: -1, y: 7 }; let Point { x: left, y: up } = q; // ✅ beim Zerlegen umbenennen println!("left = {}, up = {}", left, up);
let Meters(m) = Meters(2.5); // ✅ Tupel-Struct, Tupel-Muster println!("{} m", m);}Ausgabe:
x = 3, y = 4left = -1, up = 72.5 mBei einer Enum-Variante mit benannten Feldern, also Shape::Rect(w, h) für Rect { w: f64, h: f64 }, ergibt derselbe Fehler einen anderen Code: E0164. Die Lösung ist dieselbe: geschweifte Klammern.
Lösung 4: Eine Konstante oder einen Match Guard statt eines Funktionsaufrufs
Abschnitt betitelt „Lösung 4: Eine Konstante oder einen Match Guard statt eines Funktionsaufrufs“Nimm diese Lösung, wenn die Meldung expected a pattern, found a function call sagt (Muster erwartet, Funktionsaufruf gefunden). Ein Muster muss zur Compilezeit feststehen, und ein Funktionsaufruf tut das nicht:
error[E0532]: expected a pattern, found a function call --> src/main.rs:7:14 |7 | Some(limit()) => "full", // ❌ ein Funktionsaufruf ist kein Muster | ^^^^^ not a tuple struct or tuple variant | = note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>Das note: sagt: „Funktionsaufrufe sind in Mustern nicht erlaubt.“
Das Programm dazu:
fn limit() -> u32 { 100}
fn status(users: Option<u32>) -> &'static str { match users { Some(limit()) => "full", // ❌ ein Funktionsaufruf ist kein Muster Some(_) => "open", None => "closed", }}
fn main() { println!("{}", status(Some(100)));}Ändert sich der Wert nie, mach daraus eine const. Konstanten dürfen in Mustern stehen. Muss er berechnet werden, binde den Wert an einen Namen und vergleiche in einem Match Guard:
const LIMIT: u32 = 100; // eine Konstante darf in einem Muster stehen
fn limit_for(premium: bool) -> u32 { if premium { 500 } else { 100 }}
fn status(users: Option<u32>) -> &'static str { match users { Some(LIMIT) => "voll", // ✅ eine Konstante Some(_) => "offen", None => "geschlossen", }}
fn status_for(users: Option<u32>, premium: bool) -> &'static str { match users { Some(n) if n >= limit_for(premium) => "voll", // ✅ die Funktion im Guard aufrufen Some(_) => "offen", None => "geschlossen", }}
fn main() { println!("{}", status(Some(100))); println!("{}", status(Some(42))); println!("{}", status(None)); println!("{}", status_for(Some(100), false)); println!("{}", status_for(Some(100), true));}Ausgabe:
volloffengeschlossenvolloffenMatch Guards erklärt Match Guards: ein zusätzliches if.
Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“Nachdem eine Unit-Variante einen Wert bekommen hat. Event::Logout war früher eine Unit-Variante, und du hast daraus Logout(u64) gemacht. Jetzt ergibt jeder Event::Logout =>-Zweig E0532. Lösung: Event::Logout(_) =>, oder Event::Logout(at) =>, wenn du den Wert brauchst.
Nur die Art eines Werts prüfen. Wenn du von Java oder TypeScript kommst, schreibst du vielleicht if let Shape::Circle = shape, um zu fragen: „Ist das ein Kreis?“ Schreib if let Shape::Circle(_) = shape, oder matches!(shape, Shape::Circle(_)) für ein schnelles bool.
Ohne das Präfix Shape:: ist es E0530. Schreibst du einen nackten Namen, etwa Ok => oder Circle => nach use Shape::*;, liest rustc ihn als neue Variable. Es meldet E0530, match bindings cannot shadow tuple variants (Bindungen in einem match dürfen Tupel-Varianten nicht verdecken), mit der Hilfe try specify the pattern arguments: `Ok(..)` . Gleiche Lösung: Ergänze die Klammern.
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0533: expected unit struct, unit variant or constant, found struct variant: derselbe Fehler bei Varianten mit benannten Feldern; ergänze
{ .. }. - E0164: expected tuple struct or tuple variant, found struct variant: runde Klammern an einer Variante mit benannten Feldern oder an einer assoziierten Konstante oder Funktion.
- E0023: wrong number of fields in a tuple pattern (auf Englisch): Die Klammern stimmen, aber du hast zu viele oder zu wenige Namen angegeben.
- E0026: struct or variant does not have a field named x: ein falscher Feldname in den geschweiften Klammern eines Musters.
- E0004: non-exhaustive patterns: Nachdem du die Zweige repariert hast, muss das
matchimmer noch jede Variante abdecken. - Alle Compilerfehler: die vollständige Liste der Fehlerseiten.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Welcher match-Zweig kompiliert für enum Shape { Circle(f64), Empty }?
2. rustc sagt „expected tuple struct or tuple variant, found unit variant Status::Active“. Was ist die Lösung?
3. struct Point { x: i32, y: i32 }: Wie zerlegst du es mit let?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0532 – Rust error codes index (auf Englisch): die offizielle Erklärung dieses Fehlers.
- Mustersyntax – Das Rust-Buch: Structs und Enums zerlegen, Werte mit
_und..ignorieren, und Match Guards. - Destructuring enums – Rust by Example (auf Englisch): Unit- und Tupel-Varianten direkt nebeneinander abgleichen.
- Destructuring structs – Rust by Example (auf Englisch): geschweifte Klammern für benannte Felder, runde Klammern für Tupel-Structs.
- Patterns – The Rust Reference (auf Englisch): die genauen Regeln für Pfad-, Tupel-Struct- und Struct-Muster.