Error Rust E0063: missing field in initializer (field belum diisi)
E0063 artinya: kamu sedang membuat struct dengan Name { ... }, tapi tidak memberi nilai untuk setiap field-nya. Rust tidak pernah mengisi field untukmu, jadi setiap field butuh nilai, walaupun cuma 0, false, atau None. Pesannya menyebut nama field yang belum diisi, jadi kamu tahu persis apa yang harus ditambahkan. Ini salah satu error paling ramah di Rust. (Halaman ini bagian dari Penjelasan error compiler Rust.)
Pesan error-nya
Section titled “Pesan error-nya”error[E0063]: missing field `email` in initializer of `User` --> src/main.rs:8:16 |8 | let user = User { | ^^^^ missing `email`Artinya: field email belum diisi saat membuat User.
Ini program yang menghasilkan error tersebut:
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { name: String::from("Ferris"), active: true, // ❌ tidak ada `email` }; println!("{}", user.name);}Apa artinya
Section titled “Apa artinya”Judul error-nya menyebut field yang belum diisi (email) dan struct-nya (User). Tanda ^^^^ menunjuk ke nama struct tempat kamu mulai membuatnya, bukan ke satu baris tertentu, karena masalahnya adalah sesuatu yang tidak ada.
Kalau ada beberapa field yang belum diisi, rustc menyebutkannya berurutan sesuai abjad. Kalau hanya dua atau tiga, semuanya ditampilkan:
error[E0063]: missing fields `debug`, `retries` and `timeout_secs` in initializer of `Config`Kalau empat atau lebih, rustc menampilkan tiga dan menghitung sisanya:
error[E0063]: missing fields `debug`, `port`, `retries` and 1 other field in initializer of `Config` --> src/main.rs:10:18 |10 | let config = Config { | ^^^^^^ missing `debug`, `port`, `retries` and 1 other field“1 other field” artinya masih ada satu field lagi. Lihat definisi struct Config untuk daftar lengkapnya.
Ini seperti formulir yang semua kotaknya wajib diisi. Kamu tidak bisa menyerahkannya dengan kotak “email” kosong, walaupun niatnya mau diisi nanti.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Di banyak bahasa, field yang tidak diisi diam-diam menjadi null, 0, atau string kosong. Lalu programmu berjalan dengan pengguna yang tidak punya email, dan rusak di tempat yang jauh, sering kali di production. Rust tidak punya null, dan tidak mengarang nilai di belakangmu. Sebuah User selalu punya email sungguhan. Lihat Mendefinisikan dan membuat struct.
Bukan berarti kamu harus mengetik setiap field setiap saat. Rust memberi cara singkat untuk bilang “pakai nilai default” atau “salin sisanya dari nilai lain ini”, seperti yang ditunjukkan perbaikan di bawah. Intinya, kamu yang memilih, dan pilihan itu tertulis di kode.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Tambahkan field yang belum diisi
Section titled “Perbaikan 1: Tambahkan field yang belum diisi”Pilih ini hampir setiap saat. Field itu ada karena suatu alasan, jadi beri nilai yang sungguhan. Kalau kamu punya variabel dengan nama yang sama dengan field-nya, kamu bisa memakai shorthand User { name, email, active }.
struct User { name: String, email: String, active: bool,}
fn main() { let user = User { name: String::from("Ferris"), active: true, }; println!("{} <{}> aktif: {}", user.name, user.email, user.active);}Output:
Ferris <[email protected]> aktif: truePerbaikan 2: Derive Default dan pakai ..Default::default()
Section titled “Perbaikan 2: Derive Default dan pakai ..Default::default()”Pilih ini kalau struct-nya punya banyak field dan sebagian besar punya nilai “kosong” yang jelas, seperti pengaturan atau opsi. Tambahkan #[derive(Default)] pada struct-nya. Lalu tulis hanya field yang kamu pedulikan, dan akhiri dengan ..Default::default(). Tanda .. artinya “ambil setiap field yang tidak kutulis dari nilai ini”.
#[derive(Debug, Default)]struct Config { host: String, port: u16, debug: bool, timeout_secs: u64, retries: u8,}
fn main() { let config = Config { host: String::from("localhost"), port: 8080, ..Default::default() // ✅ debug, timeout_secs, dan retries mendapat nilai default }; println!("{:?}", config);}Output:
Config { host: "localhost", port: 8080, debug: false, timeout_secs: 0, retries: 0 }Nilai default hasil derive adalah 0 untuk angka, false untuk bool, String kosong, dan None untuk Option. Kalau 0 bukan default yang bagus (timeout 0 detik mungkin memang bukan), tulis sendiri impl Default for Config dengan nilai yang lebih baik. Lihat Default: nilai awal yang masuk akal.
Kalau kamu lupa #[derive(Default)], error-nya berubah menjadi E0277: the trait bound `Config: Default` is not satisfied (trait bound Config: Default tidak terpenuhi), dengan help: consider annotating `Config` with `#[derive(Default)]` (coba tambahkan #[derive(Default)] pada Config).
Perbaikan 3: Tulis constructor, new
Section titled “Perbaikan 3: Tulis constructor, new”Pilih ini kalau kamu membuat struct itu di banyak tempat, atau kalau beberapa field selalu dimulai dengan nilai yang sama. Taruh struct literal lengkapnya di satu fungsi, lalu panggil fungsi itu di tempat lain. Saat nanti kamu menambahkan field, kamu cukup memperbarui new, bukan setiap tempat pemanggilan.
struct Player { name: String, score: u32, level: u8,}
impl Player { fn new(name: &str) -> Player { Player { name: name.to_string(), score: 0, // setiap pemain baru mulai dari 0... level: 1, // ...di level 1 } }}
fn main() { let ana = Player::new("Ana"); let mut bo = Player::new("Bo"); bo.score += 50; println!("{}: skor {}, level {}", ana.name, ana.score, ana.level); println!("{}: skor {}, level {}", bo.name, bo.score, bo.level);}Output:
Ana: skor 0, level 1Bo: skor 50, level 1Struct literal di dalam new tetap butuh setiap field, jadi field yang terlupa akan muncul di sana sebagai E0063. Tidak masalah: kamu cukup memperbaikinya sekali. Lihat Fungsi bergaya constructor.
Perbaikan 4: Salin sisanya dari nilai lain dengan ..other
Section titled “Perbaikan 4: Salin sisanya dari nilai lain dengan ..other”Pilih ini kalau kamu sudah punya nilai yang mirip dan ingin salinannya dengan sedikit perubahan. ..base mengambil setiap field yang tidak kamu tulis dari base:
#[derive(Debug, Clone)]struct Theme { name: String, font_size: u8, dark: bool,}
fn main() { let base = Theme { name: String::from("Default"), font_size: 14, dark: false };
// hanya `name` dan `dark` yang berubah, sisanya diambil dari `base` let night = Theme { name: String::from("Malam"), dark: true, ..base };
// `..base` akan memindahkan `name` keluar dari base, jadi clone dulu supaya base tetap bisa dipakai let large = Theme { font_size: 20, ..base.clone() };
println!("{:?}", night); println!("{:?}", large); println!("{:?}", base);}Output:
Theme { name: "Malam", font_size: 14, dark: true }Theme { name: "Default", font_size: 20, dark: false }Theme { name: "Default", font_size: 14, dark: false }Satu hal yang perlu kamu tahu: ..base memindahkan (move) field seperti String keluar dari base. Di night ini tidak masalah, karena kita menulis name sendiri, jadi hanya field Copy (font_size) yang diambil dari base. Di large, name akan diambil dari base, jadi kita pakai ..base.clone() supaya base tetap bisa dipakai. Kalau kamu melewatkan clone dan memakai base setelahnya, kamu mendapat E0382.
Saat field Option membantu
Section titled “Saat field Option membantu”Kadang sebuah field memang boleh kosong: nomor telepon yang belum diberikan pengguna, nama panggilan, tanggal selesai. Jadikan field itu Option. Kamu tetap harus menuliskannya (Rust tidak mengisi None untukmu), tapi sekarang None adalah nilai yang jujur dan diizinkan. Lihat Option.
#[derive(Debug, Default)]struct Contact { name: String, email: String, phone: Option<String>, // boleh kosong nickname: Option<String>,}
fn main() { let a = Contact { name: String::from("Ana"), phone: None, // ditulis jelas: "belum ada nomor telepon" nickname: Some(String::from("Annie")), }; // dengan Default, setiap Option yang tidak kamu tulis menjadi None let b = Contact { name: String::from("Bo"), ..Default::default() };
println!("{} telepon: {:?}, panggilan: {:?}", a.name, a.phone, a.nickname); println!("{} email: {:?}, telepon: {:?}", b.name, b.email, b.phone);}Output:
Ana telepon: None, panggilan: Some("Annie")Bo email: "", telepon: NonePerhatikan bahwa b.email bernilai "". Inilah jebakan Default: field yang wajib diam-diam menjadi kosong. Pakai Option hanya untuk hal yang benar-benar opsional, dan biarkan field wajib seperti email memakai tipe biasa yang selalu kamu isi.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Tepat setelah kamu menambahkan field ke struct. Kamu menambahkan created_at ke User, dan tiba-tiba setiap User { ... } di proyekmu memberi E0063. Ini Rust sedang membantumu: setiap tempat itu perlu kamu pikirkan. Constructor new (Perbaikan 3) membuat daftar ini tetap pendek.
Varian enum dengan field bernama. Shape::Rectangle { width: 2.0 } memberi missing field `height` in initializer of `Shape`. Perhatikan bahwa pesannya menyebut enum-nya, bukan variannya. Perbaikannya: beri nilai untuk setiap field varian itu. Lihat Enum bisa menyimpan data.
Fungsi yang mengembalikan struct. Di fn new_player(name: &str) -> Player { Player { name: name.to_string(), score: 0 } }, tanda panahnya menunjuk ke Player di dalam fungsi, dengan missing `level`. Perbaikannya: tambahkan level ke literal itu.
Error terkait
Section titled “Error terkait”- E0560: struct has no field named x: kebalikannya, field yang kamu tulis tapi tidak dimiliki struct itu. Salah ketik sering memberi keduanya sekaligus.
- E0559: variant has no field named x: kesalahan nama yang sama untuk varian enum.
- E0277: trait bound not satisfied: kamu menulis
..Default::default()tapi struct-nya tidak deriveDefault. - E0451: field is private: struct-nya berasal dari modul lain dan sebagian field-nya private, jadi kamu tidak bisa mengisinya. Kalau kamu tidak menulis field private, kamu tidak mendapat E0063, melainkan “cannot construct
Accountwith struct literal syntax due to private fields” (tidak bisa membuatAccountdengan sintaks struct literal karena ada field private). Apa pun pesannya, pakai fungsinewdari modul itu. - E0382: use of moved value: kamu memakai sebuah nilai setelah
..valuememindahkan field-nya keluar. - Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. rustc bilang: missing fields a, b, c and 2 other fields. Berapa field yang belum diisi?
2. Struct-mu punya field Option<String> yang belum kamu butuhkan. Apa yang kamu tulis untuknya?
3. Apa yang dibutuhkan Config { port: 80, ..Default::default() } supaya bisa di-compile?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0063 — Rust error codes index (bahasa Inggris): penjelasan resmi error ini.
- Defining and Instantiating Structs — The Rust Book (bahasa Inggris): struct literal, field init shorthand, dan struct update syntax.
Default— dokumentasi standard library (bahasa Inggris):#[derive(Default)], menulisimpl Defaultsendiri, dan..Default::default().- Struct expressions — The Rust Reference (bahasa Inggris): aturan persis untuk
Name { field: value }dan..base. - Constructors — Rust API Guidelines (bahasa Inggris): kenapa kode Rust memakai fungsi
newuntuk membuat struct.