Error Rust E0164: expected tuple struct or tuple variant, found struct variant
E0164 artinya: kamu menulis tanda kurung di sebuah pattern, seperti Shape::Circle(r), setelah nama yang tidak menerima nilai dalam tanda kurung. Di Rust versi sekarang, kamu akan menemuinya dalam tiga situasi: varian enum dengan field bernama (Circle { radius: f64 }) yang dicocokkan seolah-olah varian tuple, fungsi asosiasi seperti Celsius::new(d) yang dipakai sebagai pattern, dan konstanta asosiasi seperti Volume::MAX(_) dengan tanda kurung di belakangnya. Masing-masing punya perbaikan yang singkat dan jelas. (Halaman ini bagian dari Penjelasan error compiler Rust.)
Pesan error-nya
Section titled “Pesan error-nya”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` punya field bernama | ^^^^^^^^^^^^^^^^ 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` punya field bernama8 + Shape::Circle { radius: _ } => 3.14 * r * r, // ❌ `Circle` punya field bernama |Ini program yang menghasilkan error tersebut:
enum Shape { Circle { radius: f64 }, Square { side: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ❌ `Circle` punya field bernama Shape::Square { side } => side * side, }}
fn main() { println!("{}", area(&Shape::Square { side: 2.0 }));}Apa artinya
Section titled “Apa artinya”^^^ menutupi seluruh pattern Shape::Circle(r), dan labelnya menyebut apa yang diharapkan Rust di situ: “a tuple struct or tuple variant” (struct tuple atau varian tuple). Hanya dua jenis hal itu yang ditulis dengan tanda kurung di sebuah pattern, karena hanya mereka yang menyimpan nilai berdasarkan posisi, seperti Some(x) atau Meters(m).
Shape::Circle adalah varian struct. Nilainya punya nama, radius, dan field bernama dicocokkan dengan kurung kurawal: Shape::Circle { radius }.
Hati-hati dengan help: di sini. Ia menyarankan Shape::Circle { radius: _ }, yang memang memperbaiki pattern-nya tapi mengabaikan radiusnya. Cabang kita memakai r, jadi kalau kamu menyalin sarannya begitu saja, kamu mendapat error baru, E0425 cannot find value `r` in this scope. Kalau kamu butuh nilainya, beri nama di dalam kurung kurawal, seperti di Perbaikan 1.
Ini seperti formulir dengan kotak berlabel, “Lebar: … Tinggi: …”, lalu kamu menulis “3, 4” di sebelah judulnya. Angkanya mungkin benar, tapi formulirnya ingin setiap angka ada di kotak berlabelnya masing-masing.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Sebuah pattern harus terlihat seperti nilai yang dicocokkannya. Rust punya dua cara untuk menyimpan data, dan masing-masing punya pattern sendiri (lihat Enum bisa menyimpan data):
| Didefinisikan sebagai | Dibuat dengan | Dicocokkan dengan |
|---|---|---|
Circle(f64) (varian tuple) |
Shape::Circle(1.0) |
Shape::Circle(r) |
Circle { radius: f64 } (varian struct) |
Shape::Circle { radius: 1.0 } |
Shape::Circle { radius } |
Field bernama dicocokkan berdasarkan nama, bukan posisi, jadi urutan di pattern tidak penting, dan menambah field nanti tidak diam-diam menggeser field lainnya. Mencampur kedua gaya itu ditolak, jadi tidak pernah ada keraguan nilai mana masuk ke mana.
Pattern juga diperiksa saat kompilasi, jadi pattern tidak bisa menjalankan kode. Itulah sebabnya nama fungsi yang diikuti (d) juga tidak bisa menjadi pattern, bahkan kalau fungsi itu membuat persis nilai yang sedang kamu cocokkan. Selengkapnya di Pattern Matching.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Pakai kurung kurawal dengan nama field-nya
Section titled “Perbaikan 1: Pakai kurung kurawal dengan nama field-nya”Pilih ini kalau pesannya bilang found struct variant, yaitu E0164 yang paling sering muncul. Tulis nama field-nya (Rust lalu membuat variabel dengan nama itu), field: nama_baru untuk memilih nama lain, atau { .. } untuk mengabaikan semua field:
enum Shape { Circle { radius: f64 }, Rect { w: f64, h: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle { radius } => 3.14 * radius * radius, // ✅ nama field di dalam kurung kurawal Shape::Rect { w: width, h: height } => width * height, // ✅ field: nama baru }}
fn name(shape: &Shape) -> &'static str { match shape { Shape::Circle { .. } => "lingkaran", // ✅ "lingkaran apa saja" Shape::Rect { .. } => "persegi panjang", }}
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)); }}Output:
lingkaran: 3.14persegi panjang: 6.00Kalau kamu menyebut sebagian field saja, tambahkan .. di akhir, seperti Shape::Rect { w, .. }. Tanpa itu kamu mendapat E0027, dan nama field yang salah ketik memberi E0026.
Perbaikan 2: Ubah variannya menjadi varian tuple
Section titled “Perbaikan 2: Ubah variannya menjadi varian tuple”Pilih ini kalau tanda kurung memang yang kamu inginkan: variannya punya satu nilai yang jelas, dan kamu lebih suka menulis Shape::Circle(1.0) di mana-mana. Ubah definisinya, maka pattern Circle(r) menjadi benar:
enum Shape { Circle(f64), // ✅ sekarang varian tuple: satu nilai tanpa nama Rect { w: f64, h: f64 },}
fn area(shape: &Shape) -> f64 { match shape { Shape::Circle(r) => 3.14 * r * r, // ✅ tanda kurung cocok untuk varian tuple Shape::Rect { w, h } => w * h, }}
fn main() { let small = Shape::Circle(1.0); // dibuat dengan tanda kurung juga 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));}Output:
3.14 12.56 2.00Ini mengubah tipenya, jadi setiap tempat yang membuat atau mencocokkan Circle juga harus beralih ke tanda kurung. Compiler akan menyebutkan satu per satu. Untuk dua nilai atau lebih, field bernama biasanya lebih jelas.
Perbaikan 3: Cocokkan struct tuple-nya langsung, dan panggil fungsi di guard
Section titled “Perbaikan 3: Cocokkan struct tuple-nya langsung, dan panggil fungsi di guard”Pilih ini kalau pesannya bilang found associated function dan labelnya bilang `fn` calls are not allowed in patterns (pemanggilan fn tidak boleh ada di pattern). Kamu menulis constructor seperti Celsius::new(d) di tempat yang membutuhkan pattern:
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` itu fungsi, bukan pattern | ^^^^^^^^^^^^^^^ `fn` calls are not allowed in patternsProgram di baliknya:
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` itu fungsi, bukan pattern _ => "cool", }}
fn main() { println!("{}", feels(Celsius::new(30.0)));}Celsius adalah struct tuple, jadi pattern-nya adalah nama struct itu sendiri: Celsius(d). Apa pun yang butuh pemanggilan fungsi atau method masuk ke match guard (if ... setelah pattern):
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 => "hangat", // ✅ struct tuple-nya sendiri, ditambah guard Celsius(_) => "sejuk", }}
fn describe(t: &Celsius) -> &'static str { match t { t if t.is_freezing() => "membeku", // ✅ method masuk ke guard _ => "tidak membeku", }}
fn main() { println!("{}", feels(Celsius::new(30.0))); println!("{}", feels(Celsius::new(12.5))); let Celsius(d) = Celsius::new(-3.0); // ✅ juga bisa dengan `let` println!("{} derajat", d); println!("{}", describe(&Celsius::new(-3.0)));}Output:
hangatsejuk-3 derajatmembekuKalau field struct-nya private (struct-nya tinggal di modul lain), kamu tidak bisa menulis Celsius(d) di luar modul itu. Kalau begitu, pakai getter di guard, seperti t if t.degrees() > 25.0. Lihat Match guard: menambahkan if.
Perbaikan 4: Hapus tanda kurung setelah konstanta
Section titled “Perbaikan 4: Hapus tanda kurung setelah konstanta”Pilih ini kalau pesannya bilang found associated constant. Sebuah konstanta sudah merupakan pattern yang lengkap. Ia mencocokkan satu nilai yang persis, jadi tidak ada yang perlu dimasukkan ke dalam tanda kurung:
error[E0164]: expected tuple struct or tuple variant, found associated constant `Volume::MAX` --> src/main.rs:10:9 |10 | Volume::MAX(_) => "loudest", // ❌ konstanta tidak memakai () | ^^^^^^^^^^^^^^ not a tuple struct or tuple variantProgram di baliknya:
struct Volume;
impl Volume { const MAX: u8 = 10;}
fn label(level: u8) -> &'static str { match level { 0 => "muted", Volume::MAX(_) => "loudest", // ❌ konstanta tidak memakai () _ => "normal", }}
fn main() { println!("{}", label(10));}Tulis konstantanya saja:
struct Volume;
impl Volume { const MAX: u8 = 10;}
fn label(level: u8) -> &'static str { match level { 0 => "senyap", Volume::MAX => "paling keras", // ✅ sebuah konstanta, tanpa apa-apa lagi 1..=3 => "pelan", _ => "normal", }}
fn main() { for level in [0, 2, 7, 10, u8::MAX] { println!("{}: {}", level, label(level)); }}Output:
0: senyap2: pelan7: normal10: paling keras255: normalHal yang sama berlaku untuk konstanta dari standard library: u32::MAX(_) adalah E0164, sedangkan u32::MAX adalah pattern yang valid.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Setelah mengubah varian menjadi field bernama. Kamu mengubah Move(i32, i32) menjadi Move { x: i32, y: i32 } supaya lebih jelas. Sekarang setiap cabang lama Command::Move(x, y) => memberi E0164. Perbaikannya: Command::Move { x, y } =>.
Mencocokkan dengan fungsi “parser”. Sesuatu seperti match input { Version::parse(v) => ... }, dengan harapan fungsinya berjalan saat pencocokan. Perbaikannya: panggil fungsinya dulu, lalu cocokkan hasilnya: match Version::parse(input) { Some(v) => ..., None => ... }.
Fungsi biasa, struct biasa, dan varian unit memberi E0532. Kesalahan tanda kurung yang sama dilaporkan sebagai E0532 kalau namanya tidak dicapai lewat sebuah tipe: fungsi biasa (Some(limit()), expected a pattern, found a function call), struct dengan field bernama (let Point(x, y) = p;, found struct `Point` ), atau varian unit (Status::Active()). Perbaikannya sama seperti di halaman ini.
Error terkait
Section titled “Error terkait”- E0532: expected tuple struct or tuple variant, found unit variant or struct: kekeliruan yang sama untuk struct biasa, varian unit, dan fungsi biasa, plus kebalikannya (varian tuple yang ditulis tanpa tanda kurung).
- E0533: expected unit struct, unit variant or constant, found struct variant: varian struct yang ditulis tanpa kurung kurawal sama sekali, seperti
Shape::Circle =>. - E0026: struct or variant does not have a field named x: kurung kurawalnya benar, tapi ada nama field yang salah di dalamnya.
- E0027: pattern does not mention field x: kurung kurawal yang melewatkan beberapa field; tambahkan
... - E0425: cannot find value in this scope: yang kamu dapat kalau menyalin saran
{ radius: _ }tapi masih memakair. - Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Untuk enum Shape { Circle { radius: f64 } }, cabang mana yang memakai radiusnya dengan benar?
2. Celsius::new(d) => ... memberi "fn calls are not allowed in patterns". Celsius adalah struct Celsius(f64);. Pattern mana yang berhasil?
3. Bagaimana cara mencocokkan konstanta asosiasi Volume::MAX?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0164 — Rust error codes index (bahasa Inggris): penjelasan resmi, dengan contoh konstanta asosiasi.
- Pattern Syntax — The Rust Book (bahasa Inggris): men-destructure enum dengan kurung kurawal atau tanda kurung, mengabaikan field dengan
.., dan match guard. - Destructuring enums — Rust by Example (bahasa Inggris): varian tuple dan varian struct dicocokkan berdampingan.
- Patterns — The Rust Reference (bahasa Inggris): path mana yang boleh muncul di pattern struct tuple dan pattern struct.