Rust-Fehler E0533: expected unit struct, unit variant or constant, found struct variant
E0533 bedeutet: Du hast einen Namen wie Shape::Circle allein hingeschrieben, aber an dieser Stelle braucht er mehr als nur seinen Namen. Meistens ist es eine Enum-Variante mit benannten Feldern (Circle { radius: f64 }), bei der die { } fehlen, entweder in einem match-Zweig oder beim Erzeugen eines Werts. Seltener ist es eine Funktion oder Methode an einer Stelle, an der nur ein fester Wert stehen darf. Beides ist schnell behoben, sobald du weißt, was rustc von dir will. (Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.)
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“error[E0533]: expected unit struct, unit variant or constant, found struct variant `Shape::Circle` --> src/main.rs:8:9 |8 | Shape::Circle => "Kreis", // ❌ `Circle` hat ein Feld | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant |help: the struct variant's field is being ignored |8 | Shape::Circle { radius: _ } => "Kreis", // ❌ `Circle` hat ein Feld | +++++++++++++Auf Deutsch: „Erwartet wurde ein Unit-Struct, eine Unit-Variante oder eine Konstante, gefunden wurde die Struct-Variante Shape::Circle.“ Das help zeigt, wie das Feld der Variante ausdrücklich ignoriert wird.
Dieses Programm erzeugt den Fehler:
enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle => "Kreis", // ❌ `Circle` hat ein Feld Shape::Square { .. } => "Quadrat", }}
fn main() { println!("{}", name(&Shape::Square { side: 2.0 }));}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Das ^^^ zeigt auf Shape::Circle, und die Überschrift erklärt, was dort erlaubt gewesen wäre. Ein Muster, das nur aus einem Namen besteht, muss eines dieser drei Dinge sein:
- ein Unit-Struct, etwa
struct Empty; - eine Unit-Variante, also eine Variante ohne Daten, etwa
Shape::EmptyoderNone - eine Konstante, etwa
const MAX: u32 = 100;
Shape::Circle ist nichts davon. Es ist eine Struct-Variante: Sie trägt einen radius. Ein nacktes Shape::Circle würde auf „einen Kreis“ passen, aber nichts über sein Feld sagen, und Rust will, dass die Form des Musters zur Form der Variante passt. Die help:-Zeile zeigt die Lösung: Ergänze die geschweiften Klammern.
Die zweite Art von E0533 lautet expected value, found struct variant (Wert erwartet, Struct-Variante gefunden). Dieselbe Verwechslung, aber beim Erzeugen eines Werts, meistens mit runden Klammern geschrieben, etwa Shape::Circle(2.0).
Das ist wie ein Paketschein mit einem Feld „Größe: S, M oder L“, in das du „Sondermaß“ geschrieben hast. Sondermaß gibt es wirklich, aber dann müssen daneben auch die Maße stehen.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“Enum-Varianten gibt es in drei Formen, und jede wird auf ihre eigene Art geschrieben, sowohl beim Erzeugen als auch beim Abfragen mit match (siehe Enums können Daten enthalten):
| Variante | Erzeugen | Abfragen |
|---|---|---|
Unit: Empty |
Shape::Empty |
Shape::Empty |
Tupel: Point(f64, f64) |
Shape::Point(1.0, 2.0) |
Shape::Point(x, y) oder Shape::Point(..) |
Struct: Circle { radius: f64 } |
Shape::Circle { radius: 2.0 } |
Shape::Circle { radius } oder Shape::Circle { .. } |
Weil Rust bei den Formen streng ist, sieht ein Muster immer so aus wie das, worauf es passt. Du kannst also ein match lesen und weißt genau, welche Daten jeder Zweig hat. Und wenn eine Variante ihre Form ändert, etwa wenn Empty ein Feld bekommt, wird jede Stelle mit der alten Form gemeldet, statt stillschweigend das Falsche zu tun.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: { .. } oder die Felder im Muster ergänzen
Abschnitt betitelt „Lösung 1: { .. } oder die Felder im Muster ergänzen“Nimm diese Lösung, wenn der Fehler auf einen Zweig in match, if let oder matches! zeigt und found struct variant sagt. Schreib { .. }, wenn du die Felder nicht brauchst, oder nenn sie, wenn du sie brauchst. Der Vorschlag von rustc, { radius: _ }, funktioniert auch, und { .. } ist die kürzere Art, dasselbe zu sagen.
enum Shape { Circle { radius: f64 }, Square { side: f64 }, Empty,}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle { .. } => "Kreis", // ✅ "ein Kreis, egal mit welchem Radius" Shape::Square { .. } => "Quadrat", Shape::Empty => "nichts", // eine Unit-Variante: keine Klammern nötig }}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ Felder genannt, weil wir sie brauchen Shape::Square { side } => side * side, Shape::Empty => 0.0, }}
fn main() { let shapes = [Shape::Circle { radius: 1.0 }, Shape::Square { side: 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.14Quadrat: 9.00nichts: 0.001 Kreis(e){ .. } funktioniert für jede Struct-Variante, egal wie viele Felder sie hat. Bei Tupel-Varianten schreibst du dieselbe Idee als (..). Siehe Teile ignorieren mit _ und ...
Lösung 2: Den Wert mit geschweiften Klammern und Feldnamen erzeugen
Abschnitt betitelt „Lösung 2: Den Wert mit geschweiften Klammern und Feldnamen erzeugen“Nimm diese Lösung, wenn die Meldung expected value, found struct variant lautet. Du erzeugst eine Struct-Variante so, als wäre sie eine Tupel-Variante (oder ganz ohne Felder):
error[E0533]: expected value, found struct variant `Shape::Circle` --> src/main.rs:8:17 |8 | let shape = Shape::Circle(2.0); // ❌ `Circle` hat ein benanntes Feld | ^^^^^^^^^^^^^ not a value |help: you might have meant to create a new value of the struct |8 - let shape = Shape::Circle(2.0); // ❌ `Circle` hat ein benanntes Feld8 + let shape = Shape::Circle { radius: /* value */ }; // ❌ `Circle` hat ein benanntes Feld |Die Markierung sagt „kein Wert“, und das help vermutet, dass du einen neuen Wert der Variante erzeugen wolltest.
Das Programm dazu:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn main() { let shape = Shape::Circle(2.0); // ❌ `Circle` hat ein benanntes Feld println!("{:?}", shape);}Das /* value */ im Vorschlag ist ein Platzhalter für deinen Wert. Die Felder einer Struct-Variante setzt du mit Namen, in geschweiften Klammern:
#[derive(Debug)]enum Shape { Circle { radius: f64 }, Square { side: f64 },}
impl Shape { // ein kurzer Konstruktor, wenn du `Shape::circle(2.0)` schreiben willst fn circle(radius: f64) -> Shape { Shape::Circle { radius } }}
fn main() { let a = Shape::Circle { radius: 2.0 }; // ✅ geschweifte Klammern und Feldname let b = Shape::Square { side: 1.5 }; let c = Shape::circle(0.5); println!("{:?}", a); println!("{:?}", b); println!("{:?}", c);}Ausgabe:
Circle { radius: 2.0 }Square { side: 1.5 }Circle { radius: 0.5 }Willst du lieber Shape::Circle(2.0) schreiben, mach aus der Definition eine Tupel-Variante: Circle(f64). Bei einem einzigen, offensichtlichen Feld ist das eine gute Wahl; bei mehreren Feldern sind Namen klarer.
Lösung 3: Eine Konstante oder einen Match Guard statt einer Funktion benutzen
Abschnitt betitelt „Lösung 3: Eine Konstante oder einen Match Guard statt einer Funktion benutzen“Nimm diese Lösung, wenn die Meldung found associated function sagt (assoziierte Funktion gefunden). Sie erscheint auch bei Methoden, etwa String::len. Ein Muster muss ein Wert sein, der schon beim Kompilieren feststeht. Ein Funktionsaufruf ist das nicht, deshalb kann der Name einer Funktion kein Muster sein:
error[E0533]: expected unit struct, unit variant or constant, found associated function `Limits::max_users` --> src/main.rs:12:9 |12 | Limits::max_users => "voll", // ❌ eine Funktion kann kein Muster sein | ^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constantDas Programm dazu:
struct Limits;
impl Limits { fn max_users() -> u32 { 100 }}
fn status(users: u32) -> &'static str { match users { 0 => "leer", Limits::max_users => "voll", // ❌ eine Funktion kann kein Muster sein _ => "offen", }}
fn main() { println!("{}", status(100));}Ändert sich der Wert nie, mach daraus eine const. Konstanten können Muster sein. Muss er berechnet werden, behalte die Funktion und vergleiche in einem Match Guard mit if:
struct Limits;
impl Limits { const MAX_USERS: u32 = 100; // eine Konstante kann als Muster dienen
fn max_rooms(premium: bool) -> u32 { if premium { 20 } else { 5 } }}
fn status(users: u32) -> &'static str { match users { 0 => "leer", Limits::MAX_USERS => "voll", // ✅ eine Konstante _ => "offen", }}
fn rooms_status(rooms: u32, premium: bool) -> &'static str { match rooms { n if n >= Limits::max_rooms(premium) => "keine weiteren Räume", // ✅ Aufruf im Guard _ => "du kannst einen Raum hinzufügen", }}
fn main() { println!("{}", status(0)); println!("{}", status(100)); println!("{}", status(42)); println!("{}", rooms_status(5, false)); println!("{}", rooms_status(5, true));}Ausgabe:
leervolloffenkeine weiteren Räumedu kannst einen Raum hinzufügenMatch Guards werden unter Match Guards: ein zusätzliches if erklärt.
Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“Nachdem eine Unit-Variante Felder bekommen hat. Status::Done war früher eine Unit-Variante, und du hast daraus Done { at: u64 } gemacht. Jetzt meldet jeder Zweig Status::Done => und jedes let s = Status::Done; den Fehler E0533. Lösung: Status::Done { .. } => in Mustern und Status::Done { at: 0 } (mit einem echten Wert) dort, wo du den Wert erzeugst.
Wenn du von einer anderen Sprache kommst. In Java oder TypeScript schreibst du vielleicht case Circle:, um nur die Art eines Werts zu prüfen. In Rust schreibst du Shape::Circle { .. } =>, oder matches!(shape, Shape::Circle { .. }) für ein schnelles bool.
Die Version für Tupel-Varianten. Bei einer Tupel-Variante wie Circle(f64) ergibt ein nackter Zweig Shape::Circle => einen anderen Code, E0532, mit derselben Überschrift „expected unit struct, unit variant or constant, found tuple variant Shape::Circle“. Die Lösung ist Shape::Circle(_) oder Shape::Circle(..). Und runde Klammern bei einer Struct-Variante in einem Muster, etwa Shape::Circle(r) => für Circle { radius: f64 }, ergeben E0164, „expected tuple struct or tuple variant, found struct variant“ (Tupel-Struct oder Tupel-Variante erwartet, Struct-Variante gefunden). Lösung: Shape::Circle { radius: r } =>.
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0559: variant has no field named x: Die geschweiften Klammern stimmen, aber ein Feldname darin ist falsch.
- E0026: struct or variant does not have a field named x: ein falscher Feldname in den geschweiften Klammern eines Musters.
- E0027: pattern does not mention field x: geschweifte Klammern in einem Muster, die Felder weglassen; ergänze
... - E0004: non-exhaustive patterns: Auch wenn die Zweige korrigiert sind, muss das
matchnoch jede Variante abdecken. E0532: expected unit struct, unit variant or constant, found tuple variant: die Version für Tupel-Varianten (siehe oben).- Alle Compilerfehler einfach erklärt
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Welcher match-Zweig kompiliert bei enum Shape { Circle { radius: f64 } }?
2. let s = Shape::Circle(2.0); ergibt „expected value, found struct variant“. Was ist die Lösung?
3. Was davon kann allein als match-Muster stehen?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0533 – Rust error codes index (auf Englisch): die offizielle Erklärung dieses Fehlers.
- Mustersyntax – Das Rust-Buch: Enums destrukturieren, Werte mit
..ignorieren und Match Guards. - Destructuring enums – Rust by Example (auf Englisch): Unit-, Tupel- und Struct-Varianten direkt nebeneinander abfragen.
- E0532 – Rust error codes index (auf Englisch): die offizielle Seite zur Tupel-Varianten-Version dieses Fehlers.
- Patterns – The Rust Reference (auf Englisch): welche Pfade als Muster erlaubt sind, und die Regeln für Struct- und Tupel-Struct-Muster.