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.)
Pesan error-nya
Section titled “Pesan error-nya”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)));}Apa artinya
Section titled “Apa artinya”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”, tapiCirclemenyimpan sebuahf64, jadi pattern yang benar butuh tanda kurung:Circle(_)atauCircle(..). - “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 cabangmatchlet bindings cannot shadow ...: diletatauif letfunction 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.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”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.
Cara memperbaikinya
Section titled “Cara memperbaikinya”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.14square: 4.00.. artinya “apa pun isinya”, dan tetap berfungsi kalau varian itu nanti menyimpan lebih banyak nilai. Lihat Mengabaikan bagian dengan _ dan ...
Perbaikan 2: Ganti nama variabelnya
Section titled “Perbaikan 2: Ganti nama variabelnya”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 structArtinya: 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 mtinggi: 1.8 mtotal: 5.5 mHal 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 staticArtinya: 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 patternstatic 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:
fullopenfullUntuk angka biasa, kamu jarang sekali butuh static. const adalah pilihan yang umum; lihat Konstanta.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”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";.
Error terkait
Section titled “Error terkait”- E0532: expected unit struct, unit variant or constant, found tuple variant: kesalahan yang sama, ditulis dengan path, seperti
Shape::Circle =>. - E0533: expected unit struct, unit variant or constant, found struct variant: varian dengan field bernama dipakai tanpa
{ .. }. - E0004: non-exhaustive patterns: setelah cabang-cabangnya kamu perbaiki,
matchtetap harus mencakup setiap varian. - E0308: mismatched types: yang kamu dapat dari
letdengan nama struct unit. - E0425: cannot find value in this scope: masalah kebalikannya, nama yang sama sekali tidak ada.
- Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”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
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0530 — Rust error codes index (bahasa Inggris): penjelasan resmi, dengan kasus
(_)yang terlupa dan kasusstaticvsconst. - Pattern Syntax — The Rust Book (bahasa Inggris): mencocokkan variabel bernama, membongkar enum, dan mengabaikan nilai dengan
_dan... - Identifier patterns — The Rust Reference (bahasa Inggris): aturan persis kapan sebuah nama di pattern menjadi variabel baru, dan kapan ia merujuk ke sesuatu yang sudah ada.
- Destructuring enums — Rust by Example (bahasa Inggris): mencocokkan varian unit dan varian tuple berdampingan.
- Static items — The Rust Reference (bahasa Inggris): beda
staticdanconst(satu tempat tetap di memori, bukan nilai yang disalin ke setiap pemakaian).