Rust-Fehler E0164: expected tuple struct or tuple variant, found struct variant
E0164 bedeutet: Du hast in einem Muster runde Klammern geschrieben, etwa Shape::Circle(r), hinter einem Namen, der keine Werte in runden Klammern annimmt. Im heutigen Rust begegnet er dir in drei Situationen: eine Enum-Variante mit benannten Feldern (Circle { radius: f64 }), die du abgleichst, als wäre sie eine Tupel-Variante; eine assoziierte Funktion wie Celsius::new(d), die du als Muster benutzt; und eine assoziierte Konstante wie Volume::MAX(_) mit Klammern dahinter. Für jeden Fall gibt es eine kurze, klare Lösung. (Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.)
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“error[E0164]: expected tuple struct or tuple variant, found struct variant `Shape::Circle` --> src/main.rs:8:9 |8 | Shape::Circle(r) => 3.14 * r * r, // ❌ `Circle` hat benannte Felder | ^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant |help: the struct variant's field is being ignored |8 - Shape::Circle(r) => 3.14 * r * r, // ❌ `Circle` hat benannte Felder8 + Shape::Circle { radius: _ } => 3.14 * r * r, // ❌ `Circle` hat benannte Felder |Auf Deutsch: „Tupel-Struct oder Tupel-Variante erwartet, Struct-Variante Shape::Circle gefunden.“ Die Hilfe sagt: „Das Feld der Struct-Variante wird ignoriert.“
Dieses Programm erzeugt den Fehler:
enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ❌ `Circle` hat benannte Felder Shape::Square { side } => side * side, }}
fn main() { println!("{}", area(&Shape::Square { side: 2.0 }));}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Die ^^^ decken das ganze Muster Shape::Circle(r) ab, und das Label sagt, was Rust dort erwartet hat: „a tuple struct or tuple variant“ (ein Tupel-Struct oder eine Tupel-Variante). Nur diese beiden Arten schreibst du in einem Muster mit runden Klammern, denn nur sie halten Werte nach Position, wie Some(x) oder Meters(m).
Shape::Circle ist eine Struct-Variante. Ihr Wert hat einen Namen, radius, und benannte Felder gleichst du mit geschweiften Klammern ab: Shape::Circle { radius }.
Vorsicht mit dem help: hier. Es schlägt Shape::Circle { radius: _ } vor. Das repariert zwar das Muster, ignoriert aber den Radius. Unser Zweig benutzt r, also ergibt der unveränderte Vorschlag einen neuen Fehler: E0425, cannot find value `r` in this scope. Wenn du den Wert brauchst, gib ihm in den geschweiften Klammern einen Namen, wie in Lösung 1.
Das ist wie ein Formular mit beschrifteten Feldern, „Breite: … Höhe: …“, und du schreibst „3, 4“ neben die Überschrift. Die Zahlen stimmen vielleicht, aber das Formular will jede in ihrem beschrifteten Feld.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“Ein Muster muss aussehen wie der Wert, den es abgleicht. Rust hat zwei Arten, Daten zu halten, und jede hat ihr eigenes Muster (siehe Enums können Daten enthalten):
| Definiert als | Erzeugt mit | Abgeglichen mit |
|---|---|---|
Circle(f64) (Tupel-Variante) |
Shape::Circle(1.0) |
Shape::Circle(r) |
Circle { radius: f64 } (Struct-Variante) |
Shape::Circle { radius: 1.0 } |
Shape::Circle { radius } |
Benannte Felder werden über den Namen abgeglichen, nicht über die Position. Die Reihenfolge im Muster spielt also keine Rolle, und ein später hinzugefügtes Feld verschiebt die anderen nicht heimlich. Beide Stile zu mischen ist verboten, darum gibt es nie Zweifel, welcher Wert wohin gehört.
Muster werden außerdem zur Compilezeit geprüft, also können sie keinen Code ausführen. Deshalb kann auch ein Funktionsname mit (d) dahinter kein Muster sein, selbst wenn die Funktion genau den Wert baut, den du abgleichst. Mehr dazu unter Pattern Matching.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: Geschweifte Klammern mit den Feldnamen benutzen
Abschnitt betitelt „Lösung 1: Geschweifte Klammern mit den Feldnamen benutzen“Nimm diese Lösung, wenn die Meldung found struct variant sagt. Das ist das häufigste E0164. Schreib den Feldnamen (Rust legt dann eine Variable mit diesem Namen an), feld: neuer_name für einen anderen Namen, oder { .. }, um alle Felder zu ignorieren:
enum Shape { Circle { radius: f64 }, Rect { w: f64, h: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ Feldname in geschweiften Klammern Shape::Rect { w: width, h: height } => width * height, // ✅ feld: neuer Name }}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle { .. } => "Kreis", // ✅ „irgendein Kreis“ Shape::Rect { .. } => "Rechteck", }}
fn main() { let shapes = [Shape::Circle { radius: 1.0 }, Shape::Rect { w: 2.0, h: 3.0 }]; for shape in &shapes { println!("{}: {:.2}", name(shape), area(shape)); }}Ausgabe:
Kreis: 3.14Rechteck: 6.00Nennst du nur einige Felder, schreib .. ans Ende, etwa Shape::Rect { w, .. }. Ohne das bekommst du E0027, und ein falsch geschriebener Feldname ergibt E0026.
Lösung 2: Die Variante zu einer Tupel-Variante machen
Abschnitt betitelt „Lösung 2: Die Variante zu einer Tupel-Variante machen“Nimm diese Lösung, wenn du wirklich runde Klammern willst: Die Variante hat einen einzigen, offensichtlichen Wert, und du schreibst lieber überall Shape::Circle(1.0). Ändere die Definition, dann ist das Muster Circle(r) richtig:
enum Shape { Circle(f64), // ✅ jetzt eine Tupel-Variante: ein Wert ohne Namen Rect { w: f64, h: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ✅ runde Klammern passen zu einer Tupel-Variante Shape::Rect { w, h } => w * h, }}
fn main() { let small = Shape::Circle(1.0); // auch beim Erzeugen mit runden Klammern let big = Shape::Circle(2.0); let door = Shape::Rect { w: 1.0, h: 2.0 }; println!("{:.2} {:.2} {:.2}", area(&small), area(&big), area(&door));}Ausgabe:
3.14 12.56 2.00Damit änderst du den Typ. Jede Stelle, die Circle erzeugt oder abgleicht, muss also ebenfalls auf runde Klammern umstellen. Der Compiler zeigt dir jede einzelne. Bei zwei oder mehr Werten sind benannte Felder meist klarer.
Lösung 3: Das Tupel-Struct selbst abgleichen und Funktionen im Guard aufrufen
Abschnitt betitelt „Lösung 3: Das Tupel-Struct selbst abgleichen und Funktionen im Guard aufrufen“Nimm diese Lösung, wenn die Meldung found associated function sagt und das Label `fn` calls are not allowed in patterns (fn-Aufrufe sind in Mustern nicht erlaubt). Du hast einen Konstruktor wie Celsius::new(d) geschrieben, wo Rust ein Muster braucht:
error[E0164]: expected tuple struct or tuple variant, found associated function `Celsius::new` --> src/main.rs:11:9 |11 | Celsius::new(d) if d > 25.0 => "warm", // ❌ `new` ist eine Funktion, kein Muster | ^^^^^^^^^^^^^^^ `fn` calls are not allowed in patternsDas Programm dazu:
struct Celsius(f64);
impl Celsius { fn new(degrees: f64) -> Celsius { Celsius(degrees) }}
fn feels(t: Celsius) -> &'static str { match t { Celsius::new(d) if d > 25.0 => "warm", // ❌ `new` ist eine Funktion, kein Muster _ => "cool", }}
fn main() { println!("{}", feels(Celsius::new(30.0)));}Celsius ist ein Tupel-Struct, also ist das Muster der Name des Structs selbst: Celsius(d). Alles, was einen Funktions- oder Methodenaufruf braucht, gehört in einen Match Guard (if ... hinter dem Muster):
struct Celsius(f64);
impl Celsius { fn new(degrees: f64) -> Celsius { Celsius(degrees) }
fn is_freezing(&self) -> bool { self.0 <= 0.0 }}
fn feels(t: Celsius) -> &'static str { match t { Celsius(d) if d > 25.0 => "warm", // ✅ das Tupel-Struct selbst, plus ein Guard Celsius(_) => "kühl", }}
fn describe(t: &Celsius) -> &'static str { match t { t if t.is_freezing() => "Frost", // ✅ Methoden gehören in einen Guard _ => "kein Frost", }}
fn main() { println!("{}", feels(Celsius::new(30.0))); println!("{}", feels(Celsius::new(12.5))); let Celsius(d) = Celsius::new(-3.0); // ✅ funktioniert auch mit `let` println!("{} Grad", d); println!("{}", describe(&Celsius::new(-3.0)));}Ausgabe:
warmkühl-3 GradFrostIst das Feld des Structs privat (weil es in einem anderen Modul liegt), kannst du außerhalb dieses Moduls nicht Celsius(d) schreiben. Nimm dann einen Getter in einem Guard, etwa t if t.degrees() > 25.0. Siehe Match Guards: ein zusätzliches if.
Lösung 4: Die Klammern hinter einer Konstante weglassen
Abschnitt betitelt „Lösung 4: Die Klammern hinter einer Konstante weglassen“Nimm diese Lösung, wenn die Meldung found associated constant sagt. Eine Konstante ist schon ein vollständiges Muster. Sie passt auf genau einen Wert, also gibt es nichts, was in Klammern gehört:
error[E0164]: expected tuple struct or tuple variant, found associated constant `Volume::MAX` --> src/main.rs:10:9 |10 | Volume::MAX(_) => "loudest", // ❌ eine Konstante nimmt keine () | ^^^^^^^^^^^^^^ not a tuple struct or tuple variantDas Programm dazu:
struct Volume;
impl Volume { const MAX: u8 = 10;}
fn label(level: u8) -> &'static str { match level { 0 => "muted", Volume::MAX(_) => "loudest", // ❌ eine Konstante nimmt keine () _ => "normal", }}
fn main() { println!("{}", label(10));}Schreib die Konstante allein hin:
struct Volume;
impl Volume { const MAX: u8 = 10;}
fn label(level: u8) -> &'static str { match level { 0 => "stumm", Volume::MAX => "am lautesten", // ✅ eine Konstante, allein 1..=3 => "leise", _ => "normal", }}
fn main() { for level in [0, 2, 7, 10, u8::MAX] { println!("{}: {}", level, label(level)); }}Ausgabe:
0: stumm2: leise7: normal10: am lautesten255: normalDasselbe gilt für Konstanten aus der Standardbibliothek: u32::MAX(_) ist E0164, u32::MAX ist ein gültiges Muster.
Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“Nachdem du eine Variante auf benannte Felder umgestellt hast. Du hast Move(i32, i32) der Klarheit halber zu Move { x: i32, y: i32 } gemacht. Jetzt ergibt jeder alte Command::Move(x, y) =>-Zweig E0164. Lösung: Command::Move { x, y } =>.
Abgleich mit einer „Parser“-Funktion. Zum Beispiel match input { Version::parse(v) => ... }, in der Hoffnung, dass die Funktion beim Abgleichen läuft. Lösung: Ruf sie zuerst auf und gleiche dann das Ergebnis ab: match Version::parse(input) { Some(v) => ..., None => ... }.
Freie Funktionen, normale Structs und Unit-Varianten ergeben stattdessen E0532. Derselbe Klammerfehler wird als E0532 gemeldet, wenn der Name nicht über einen Typ erreicht wird: eine normale Funktion (Some(limit()), expected a pattern, found a function call), ein Struct mit benannten Feldern (let Point(x, y) = p;, found struct `Point` ) oder eine Unit-Variante (Status::Active()). Die Lösungen sind dieselben wie auf dieser Seite.
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0532: expected tuple struct or tuple variant, found unit variant or struct: dieselbe Verwechslung bei normalen Structs, Unit-Varianten und freien Funktionen, und das Gegenstück (eine Tupel-Variante ohne Klammern).
- E0533: expected unit struct, unit variant or constant, found struct variant: eine Struct-Variante ganz ohne geschweifte Klammern, etwa
Shape::Circle =>. - E0026: struct or variant does not have a field named x: Die geschweiften Klammern stimmen, aber ein Feldname darin ist falsch.
- E0027: pattern does not mention field x: geschweifte Klammern, in denen Felder fehlen; ergänze
... - E0425: cannot find value in this scope: was du bekommst, wenn du den Vorschlag
{ radius: _ }übernimmst, aber weiterrbenutzt. - Alle Compilerfehler: die vollständige Liste der Fehlerseiten.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Welcher Zweig benutzt den Radius bei enum Shape { Circle { radius: f64 } } richtig?
2. Celsius::new(d) => ... ergibt „fn calls are not allowed in patterns“. Celsius ist struct Celsius(f64);. Welches Muster funktioniert?
3. Wie gleichst du die assoziierte Konstante Volume::MAX ab?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0164 – Rust error codes index (auf Englisch): die offizielle Erklärung, mit dem Beispiel zur assoziierten Konstante.
- Mustersyntax – Das Rust-Buch: Enums mit geschweiften oder runden Klammern zerlegen, Felder mit
..ignorieren, und Match Guards. - Destructuring enums – Rust by Example (auf Englisch): Tupel- und Struct-Varianten direkt nebeneinander abgleichen.
- Patterns – The Rust Reference (auf Englisch): welche Pfade in Tupel-Struct-Mustern und Struct-Mustern stehen dürfen.