Lewati ke konten

Error Rust E0532: expected unit struct, unit variant or constant, found tuple variant

E0532 artinya: bentuk pattern-mu tidak cocok dengan bentuk hal yang kamu sebut. Contoh klasiknya adalah cabang match seperti Shape::Circle => untuk varian yang menyimpan data, Circle(f64). Rust ingin ada tanda kurungnya: Shape::Circle(_). Kesalahan kebalikannya mendapat kode yang sama, dengan kalimat lain, “expected tuple struct or tuple variant”: tanda kurung pada sesuatu yang tidak punya data dalam tanda kurung, seperti Status::Active(). Keduanya bisa diperbaiki dalam satu baris. (Halaman ini bagian dari Penjelasan error compiler Rust.)

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` menyimpan sebuah nilai
| ^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `Shape::Circle(_)`

Ini program yang menghasilkan error tersebut:

enum Shape {
Circle(f64),
Square(f64),
}
fn name(shape: &Shape) -> &'static str {
match shape {
Shape::Circle => "circle", // ❌ `Circle` menyimpan sebuah nilai
Shape::Square(_) => "square",
}
}
fn main() {
println!("{}", name(&Shape::Circle(1.0)));
}

^^^ menunjuk ke Shape::Circle di baris 8, dan --- di baris 2 menunjukkan cara varian itu didefinisikan: Circle(f64), sebuah varian tuple yang membawa satu f64. Pattern yang hanya berupa nama, tanpa apa pun di belakangnya, harus salah satu dari tiga hal ini:

  • unit struct, seperti struct Empty;
  • varian unit, yaitu varian tanpa data, seperti Shape::Empty atau None
  • konstanta, seperti const LIMIT: u32 = 100;

Shape::Circle bukan salah satunya. Baris help langsung memberi perbaikannya: Shape::Circle(_), artinya “sebuah lingkaran, apa pun nilainya”.

Judul E0532 yang lain adalah kebalikannya: expected tuple struct or tuple variant, found unit variant `Status::Active` (atau found struct, atau found constant). Di situ, kamu yang menulis tanda kurung setelah sebuah nama, padahal hal yang kamu sebut tidak menerima nilai dalam tanda kurung.

Ini seperti formulir yang bertanya “Hewan peliharaan: anjing (nama: ____)”. Kalau kamu hanya menulis “anjing”, kotak namanya kosong. Kalau kamu menulis “ikan (nama: Bubbles)” padahal formulirnya hanya bilang “ikan” tanpa kotak, kamu menambah kotak yang memang tidak ada.

Setiap struct dan varian enum punya salah satu dari tiga bentuk, dan kamu menulisnya dengan cara yang sama saat membuatnya maupun saat mencocokkannya (lihat Enum bisa menyimpan data):

Jenis Membuatnya Mencocokkannya
Unit: Empty Shape::Empty Shape::Empty
Tuple: Circle(f64) Shape::Circle(1.0) Shape::Circle(r) atau Shape::Circle(..)
Struct: Rect { w: f64, h: f64 } Shape::Rect { w: 2.0, h: 3.0 } Shape::Rect { w, h } atau Shape::Rect { .. }

Karena bentuknya ketat, sebuah pattern selalu terlihat seperti nilai yang dicocokkannya, jadi kamu bisa membaca sebuah match dan langsung tahu data apa yang ada di setiap cabang. Ini juga membantu saat kamu mengubah sebuah tipe: kalau Empty nanti mendapat nilai dan menjadi Empty(u32), setiap cabang lama Shape::Empty ditandai, alih-alih diam-diam mencocokkan sesuatu yang baru.

Perbaikan 1: Tambahkan (_), (..), atau nama untuk nilainya

Section titled “Perbaikan 1: Tambahkan (_), (..), atau nama untuk nilainya”

Pilih ini kalau pesannya bilang found tuple variant atau found tuple struct, yaitu E0532 yang paling sering muncul. Pakai _ untuk setiap nilai yang tidak kamu butuhkan, .. untuk melewatkan semuanya sekaligus, atau sebuah nama kalau kamu ingin memakai nilainya:

enum Shape {
Circle(f64),
Rect(f64, f64),
Empty,
}
fn name(shape: &Shape) -> &'static str {
match shape {
Shape::Circle(_) => "lingkaran", // ✅ satu field, diabaikan
Shape::Rect(..) => "persegi panjang", // ✅ berapa pun field-nya, semuanya diabaikan
Shape::Empty => "kosong", // varian unit: tanpa tanda kurung
}
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle(r) => 3.14 * r * r, // ✅ ikat field-nya karena kita membutuhkannya
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!("{} lingkaran", circles);
}

Output:

lingkaran: 3.14
persegi panjang: 6.00
kosong: 0.00
1 lingkaran
▶ Coba sendiri

(..) praktis untuk varian dengan beberapa nilai, dan tetap berfungsi kalau nanti kamu menambah satu nilai lagi. Lihat Mengabaikan bagian dengan _ dan ...

Pilih ini kalau pesannya bilang found unit variant atau found unit struct. Variannya tidak menyimpan data, jadi tidak ada yang bisa dimasukkan ke dalam tanda kurung:

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` tidak menyimpan data
| ^^^^^^^^^^^^^^^^ help: use this syntax instead: `Status::Active`

Artinya: yang diharapkan struct tuple atau varian tuple, tapi yang ditemukan varian unit, dan help-nya menyarankan menulis Status::Active saja. Program di baliknya:

enum Status {
Active,
Banned(String),
}
fn label(s: &Status) -> &'static str {
match s {
Status::Active() => "active", // ❌ `Active` tidak menyimpan data
Status::Banned(_) => "banned",
}
}
fn main() {
println!("{}", label(&Status::Active));
}

Tulis namanya saja, baik di pattern maupun saat kamu membuat nilainya:

#[derive(Debug)]
enum Status {
Active,
Banned(String),
}
fn label(s: &Status) -> String {
match s {
Status::Active => String::from("aktif"), // ✅ varian unit: tanpa ()
Status::Banned(reason) => format!("diblokir ({})", reason),
}
}
fn main() {
println!("{}", label(&Status::Active));
println!("{}", label(&Status::Banned(String::from("spam"))));
let s = Status::Active; // ✅ dan tanpa () juga saat membuatnya
println!("{:?}", s);
}

Output:

aktif
diblokir (spam)
Active
▶ Coba sendiri

Kalau kamu memang ingin variannya membawa data, ubah definisinya saja, misalnya Active(u64) untuk timestamp “sejak kapan”, lalu Status::Active(_) menjadi pattern yang benar.

Perbaikan 3: Pakai kurung kurawal untuk struct dengan field bernama

Section titled “Perbaikan 3: Pakai kurung kurawal untuk struct dengan field bernama”

Pilih ini kalau pesannya bilang found struct. Struct dengan field bernama, struct Point { x: i32, y: i32 }, di-destructure dengan kurung kurawal dan nama field-nya, bukan dengan tanda kurung:

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` punya field bernama
| ^^^^^^^^^^^ help: use struct pattern syntax instead: `Point { x, y }`

Artinya: Point adalah struct dengan field bernama, jadi rustc menyarankan sintaks pattern struct, Point { x, y }. Program di baliknya:

struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 3, y: 4 };
let Point(x, y) = p; // ❌ `Point` punya field bernama
println!("{} {}", x, y);
}

Saran rustc, Point { x, y }, sudah tepat. Pakai field: nama kalau kamu ingin nama variabel yang berbeda:

struct Point {
x: i32,
y: i32,
}
struct Meters(f64); // struct tuple: di sini tanda kurung memang benar
fn main() {
let p = Point { x: 3, y: 4 };
let Point { x, y } = p; // ✅ kurung kurawal dan nama field-nya
println!("x = {}, y = {}", x, y);
let q = Point { x: -1, y: 7 };
let Point { x: left, y: up } = q; // ✅ ganti nama sambil men-destructure
println!("left = {}, up = {}", left, up);
let Meters(m) = Meters(2.5); // ✅ struct tuple, pattern tuple
println!("{} m", m);
}

Output:

x = 3, y = 4
left = -1, up = 7
2.5 m
▶ Coba sendiri

Untuk varian enum dengan field bernama, Shape::Rect(w, h) untuk Rect { w: f64, h: f64 }, kesalahan yang sama memberi kode lain, E0164. Perbaikannya sama: kurung kurawal.

Perbaikan 4: Pakai konstanta atau match guard, bukan pemanggilan fungsi

Section titled “Perbaikan 4: Pakai konstanta atau match guard, bukan pemanggilan fungsi”

Pilih ini kalau pesannya bilang expected a pattern, found a function call. Pattern harus sudah diketahui saat kompilasi, dan pemanggilan fungsi tidak memenuhi syarat itu:

error[E0532]: expected a pattern, found a function call
--> src/main.rs:7:14
|
7 | Some(limit()) => "full", // ❌ pemanggilan fungsi tidak bisa jadi pattern
| ^^^^^ 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>

Artinya: yang diharapkan sebuah pattern, tapi yang ditemukan pemanggilan fungsi, dan note:-nya mengingatkan bahwa pemanggilan fungsi tidak boleh ada di dalam pattern. Program di baliknya:

fn limit() -> u32 {
100
}
fn status(users: Option<u32>) -> &'static str {
match users {
Some(limit()) => "full", // ❌ pemanggilan fungsi tidak bisa jadi pattern
Some(_) => "open",
None => "closed",
}
}
fn main() {
println!("{}", status(Some(100)));
}

Kalau nilainya tidak pernah berubah, jadikan const; konstanta boleh dipakai di dalam pattern. Kalau nilainya harus dihitung, ikat nilainya ke sebuah nama dan bandingkan di match guard:

const LIMIT: u32 = 100; // konstanta boleh dipakai di dalam pattern
fn limit_for(premium: bool) -> u32 {
if premium { 500 } else { 100 }
}
fn status(users: Option<u32>) -> &'static str {
match users {
Some(LIMIT) => "penuh", // ✅ sebuah konstanta
Some(_) => "buka",
None => "tutup",
}
}
fn status_for(users: Option<u32>, premium: bool) -> &'static str {
match users {
Some(n) if n >= limit_for(premium) => "penuh", // ✅ panggil fungsinya di guard
Some(_) => "buka",
None => "tutup",
}
}
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));
}

Output:

penuh
buka
tutup
penuh
buka
▶ Coba sendiri

Match guard dijelaskan di Match guard: menambahkan if.

Setelah varian unit mendapat nilai. Event::Logout tadinya varian unit, lalu kamu mengubahnya menjadi Logout(u64). Sekarang setiap cabang Event::Logout => memberi E0532. Perbaikannya: Event::Logout(_) =>, atau Event::Logout(at) => kalau kamu butuh nilainya.

Hanya ingin mengecek jenis sebuah nilai. Kalau kamu datang dari Java atau TypeScript, kamu mungkin menulis if let Shape::Circle = shape untuk bertanya “apakah ini lingkaran?”. Tulis if let Shape::Circle(_) = shape, atau matches!(shape, Shape::Circle(_)) untuk mendapat bool dengan cepat.

Tanpa awalan Shape::, kodenya E0530. Kalau kamu menulis nama saja, seperti Ok => atau Circle => setelah use Shape::*;, rustc membacanya sebagai variabel baru. Ia melaporkan E0530, match bindings cannot shadow tuple variants (binding di match tidak boleh menutupi varian tuple), dengan help try specify the pattern arguments: `Ok(..)` . Perbaikannya sama: tambahkan tanda kurungnya.

Kuis singkat

1. Untuk enum Shape { Circle(f64), Empty }, cabang match mana yang bisa dikompilasi?

2. rustc bilang "expected tuple struct or tuple variant, found unit variant Status::Active". Apa perbaikannya?

3. struct Point { x: i32, y: i32 }: bagaimana cara men-destructure-nya dengan let?

Skor: 0 / 3