Zum Inhalt springen

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

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

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::Empty oder None
  • 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.

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.

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.14
Rechteck: 6.00
nichts: 0.00
1 Kreis(e)
▶ Selbst ausprobieren

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

aktiv
gesperrt (Spam)
Active
▶ Selbst ausprobieren

Wolltest 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 = 4
left = -1, up = 7
2.5 m
▶ Selbst ausprobieren

Bei 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:

voll
offen
geschlossen
voll
offen
▶ Selbst ausprobieren

Match Guards erklärt Match Guards: ein zusätzliches if.

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.

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