Lewati ke konten

Error Rust E0530: match bindings cannot shadow tuple variants (nama bentrok)

E0530 artinya: sebuah nama di pattern-mu sudah dipakai oleh hal lain. Kamu menulis nama biasa, seperti Circle, di tempat Rust biasanya membuat variabel baru. Tapi Circle sudah punya arti lain di scope ini: sebuah varian tuple, sebuah struct tuple, atau sebuah static. Rust menolak menyembunyikannya diam-diam di balik variabel baru, karena itu hampir tidak pernah yang kamu maksud. Kasus klasiknya adalah cabang match Circle => setelah use Shape::*;, dan perbaikannya biasanya cuma dua karakter: Circle(..). (Halaman ini bagian dari Penjelasan error compiler Rust.)

error[E0530]: match bindings cannot shadow tuple variants
--> src/main.rs:10:9
|
6 | use Shape::*;
| -------- the tuple variant `Circle` is imported here
...
10 | Circle => "circle", // ❌ `Circle` holds a value
| ^^^^^^
| |
| cannot be named the same as a tuple variant
| help: try specify the pattern arguments: `Circle(..)`

Artinya: binding di match tidak boleh menutupi (shadow) varian tuple. rustc menunjukkan dari mana nama Circle berasal, dan help-nya menyarankan menulis Circle(..).

Ini program yang menghasilkan error tersebut:

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

Tanda ^^^ menunjuk ke Circle di baris 10, dan tanda --- di baris 6 menunjukkan asal nama itu: use Shape::*; membawa varian Shape::Circle ke dalam scope.

Di dalam pattern, nama biasa seperti x atau other membuat variabel baru yang cocok dengan nilai apa pun. Jadi Circle => bisa berarti dua hal:

  • “cocokkan dengan varian Circle”, tapi Circle menyimpan sebuah f64, jadi pattern yang benar butuh tanda kurung: Circle(_) atau Circle(..).
  • “cocokkan dengan apa saja dan beri nama Circle”, sebuah variabel baru yang akan menyembunyikan variannya.

Rust tidak mau menebak. Judul error-nya memberi tahu jenis nama yang bentrok, dan kata pertamanya memberi tahu di mana:

  • match bindings cannot shadow ...: di cabang match
  • let bindings cannot shadow ...: di let atau if let
  • function parameters cannot shadow ...: di daftar parameter fungsi

dan diakhiri dengan tuple variants (varian tuple), tuple structs (struct tuple), atau statics.

Ibaratnya kamu menamai anjingmu “Dokter”. Setiap kali seseorang memanggil “Dokter!” di ruang tunggu, tidak ada yang tahu siapa yang dimaksud.

Tanpa aturan ini, Circle => akan menjadi variabel baru bernama Circle. Variabel itu cocok dengan setiap nilai, dan semua cabang sesudahnya jadi kode mati. Programmu akan ter-compile, lalu mencetak “circle” untuk persegi juga. Itu bug yang menyebalkan, yang bersembunyi di balik kode yang kelihatan benar.

Jadi Rust menjadikannya error setiap kali sebuah variabel baru akan memakai nama varian tuple, struct tuple, atau static. Kamu harus menyatakan maksudmu dengan tanda kurung, atau memilih nama lain. Varian unit seperti None dan konstanta (const) berbeda: keduanya sudah merupakan pattern yang valid, jadi Rust membacanya sebagai “cocokkan dengan nilai ini”. Lihat Pattern Matching dan Enum.

Perbaikan 1: Tambahkan (..) atau (_) untuk mencocokkan variannya

Section titled “Perbaikan 1: Tambahkan (..) atau (_) untuk mencocokkan variannya”

Pilih ini kalau pesannya menyebut tuple variants atau tuple structs, yang merupakan kasus paling umum. Yang kamu maksud adalah variannya, jadi beri tanda kurungnya, seperti saran help dari rustc. Menulis path lengkapnya, Shape::Circle(_), bahkan lebih jelas:

enum Shape {
Circle(f64),
Square(f64),
}
use Shape::*;
fn name(shape: &Shape) -> &'static str {
match shape {
Circle(..) => "circle", // ✅ variannya, dengan nilai apa pun di dalamnya
Square(_) => "square",
}
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle(r) => 3.14 * r * r, // ✅ path lengkap, dan pakai nilainya
Shape::Square(side) => side * side,
}
}
fn main() {
let shapes = [Circle(1.0), Square(2.0)];
for shape in &shapes {
println!("{}: {:.2}", name(shape), area(shape));
}
}

Output:

circle: 3.14
square: 4.00
▶ Coba sendiri

.. artinya “apa pun isinya”, dan tetap berfungsi kalau varian itu nanti menyimpan lebih banyak nilai. Lihat Mengabaikan bagian dengan _ dan ...

Pilih ini kalau kamu memang ingin variabel baru, dan namanya kebetulan sama dengan sebuah tipe. Ini sering terjadi pada let dan parameter fungsi, saat kamu menamai variabel sesuai tipenya:

error[E0530]: let bindings cannot shadow tuple structs
--> src/main.rs:4:9
|
1 | struct Meters(f64);
| ------------------- the tuple struct `Meters` is defined here
...
4 | let Meters = 5.0; // ❌ `Meters` is a tuple struct
| ^^^^^^ cannot be named the same as a tuple struct

Artinya: binding let tidak boleh menutupi struct tuple Meters yang didefinisikan di baris 1. Program di baliknya:

struct Meters(f64);
fn main() {
let Meters = 5.0; // ❌ `Meters` is a tuple struct
println!("{}", Meters);
}

Gaya penamaan Rust sudah menyelesaikan masalah ini: tipe dan varian ditulis CamelCase, variabel ditulis snake_case. Pakai nama huruf kecil, dan bentroknya hilang:

struct Meters(f64);
fn total(meters: &[Meters]) -> f64 {
meters.iter().map(|m| m.0).sum()
}
fn main() {
let meters = 5.0; // ✅ nama variabel huruf kecil
println!("{} m", meters);
let Meters(height) = Meters(1.8); // ✅ atau bongkar (destructure) struct tuple-nya
println!("tinggi: {} m", height);
println!("total: {} m", total(&[Meters(2.0), Meters(3.5)]));
}

Output:

5 m
tinggi: 1.8 m
total: 5.5 m
▶ Coba sendiri

Hal yang sama berlaku untuk parameter: fn show(Point: i32) memberi function parameters cannot shadow tuple structs, dan fn show(point: i32) memperbaikinya. Lihat Aturan penamaan.

Perbaikan 3: Pakai const (atau match guard) sebagai ganti static

Section titled “Perbaikan 3: Pakai const (atau match guard) sebagai ganti static”

Pilih ini kalau pesannya menyebut statics. Kemungkinan besar kamu ingin membandingkan dengan nilai tetap. Sebuah static tidak bisa dipakai sebagai pattern, tapi const bisa:

error[E0530]: match bindings cannot shadow statics
--> src/main.rs:5:9
|
1 | static LIMIT: u32 = 100;
| ------------------------ the static `LIMIT` is defined here
...
5 | LIMIT => "full", // ❌ a static can't be a pattern
| ^^^^^ cannot be named the same as a static

Artinya: binding di match tidak boleh menutupi static LIMIT. Program di baliknya:

static LIMIT: u32 = 100;
fn status(users: u32) -> &'static str {
match users {
LIMIT => "full", // ❌ a static can't be a pattern
_ => "open",
}
}
fn main() {
println!("{}", status(100));
}

Ganti static menjadi const. Kalau nilainya harus tetap static (misalnya karena ada kode lain yang mengambil alamatnya), ikat nilainya ke sebuah nama lalu bandingkan di match guard:

const LIMIT: u32 = 100; // ✅ const bisa dipakai sebagai pattern
static MAX_USERS: u32 = 500; // static tetap static
fn status(users: u32) -> &'static str {
match users {
LIMIT => "full",
_ => "open",
}
}
fn premium_status(users: u32) -> &'static str {
match users {
n if n >= MAX_USERS => "full", // ✅ bandingkan static di dalam guard
_ => "open",
}
}
fn main() {
println!("{}", status(100));
println!("{}", status(42));
println!("{}", premium_status(500));
}

Output:

full
open
full
▶ Coba sendiri

Untuk angka biasa, kamu jarang sekali butuh static. const adalah pilihan yang umum; lihat Konstanta.

Ok => atau Some => tanpa tanda kurung. Ok, Err, dan Some adalah varian tuple dari prelude, jadi match result { Ok => ... } memberi E0530 dengan help try specify the pattern arguments: `Ok(..)` . Perbaikannya: Ok(_) => atau Ok(value) =>.

Di dalam if let. if let Some(Some) = x mencoba menamai nilai di dalamnya Some, dan memberi let bindings cannot shadow tuple variants. Perbaikannya: nama huruf kecil, if let Some(inner) = x.

Dengan path lengkap, error-nya jadi E0532. Shape::Circle => tidak mungkin menjadi variabel baru (nama variabel tidak punya ::), jadi rustc melaporkan E0532, expected unit struct, unit variant or constant, found tuple variant. Perbaikannya sama: tambahkan (_) atau (..).

let dengan nama struct unit memberi E0308. Dengan struct Guest;, baris let Guest = "Ana"; sama sekali tidak membuat variabel: rustc membaca Guest sebagai struct unit dan melaporkan E0308 (mismatched types, tipe tidak cocok), dengan keterangan `Guest` is interpreted as a unit struct, not a new binding (Guest dibaca sebagai struct unit, bukan binding baru). Perbaikannya: ganti nama variabelnya, let guest = "Ana";.

Kuis singkat

1. Setelah use Shape::*;, dengan Circle(f64) sebagai varian, cabang match mana yang bisa ter-compile?

2. rustc bilang "let bindings cannot shadow tuple structs" untuk let Meters = 5.0;. Apa perbaikan paling sederhana?

3. static LIMIT: u32 = 100; tidak bisa dipakai sebagai pattern di match. Apa yang bisa?

Skor: 0 / 3