Zum Inhalt springen

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

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

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

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.

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

{ .. } 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 Feld
8 + 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 }
▶ Selbst ausprobieren

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 constant

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

leer
voll
offen
keine weiteren Räume
du kannst einen Raum hinzufügen
▶ Selbst ausprobieren

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

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 } =>.

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