Error Rust E0424: expected value, found module `self` (tanpa parameter self)
E0424 artinya kamu menulis self di dalam fungsi yang tidak punya parameter self, jadi tidak ada “self” yang bisa ditunjuk oleh Rust. Ini kekeliruan yang sangat umum, apalagi kalau kamu datang dari Java, C#, atau JavaScript, tempat this selalu tersedia. Perbaikannya biasanya cuma satu kata: tambahkan &self ke daftar parameter fungsinya. Halaman ini bagian dari Penjelasan error compiler Rust.
Pesan error-nya
Section titled “Pesan error-nya”error[E0424]: expected value, found module `self` --> src/main.rs:7:32 |6 | fn describe() { | -------- this function doesn't have a `self` parameter7 | println!("Player: {}", self.name); // ❌ which player? | ^^^^ `self` value is a keyword only available in methods with a `self` parameter |help: add a `self` receiver parameter to make the associated `fn` a method |6 | fn describe(&self) { | +++++
error[E0599]: no method named `describe` found for struct `Player` in the current scope --> src/main.rs:13:10 |13 | hero.describe(); | ^^^^^^^^ this is an associated function, not a methodCompiler bilang self hanya bisa dipakai di method yang punya parameter self, dan menyarankan untuk menambahkan &self ke describe.
Ini program yang menghasilkan error tersebut:
struct Player { name: String,}
impl Player { fn describe() { println!("Player: {}", self.name); // ❌ which player? }}
fn main() { let hero = Player { name: String::from("Ferris") }; hero.describe();}(Komentar which player? artinya “pemain yang mana?”.) Error kedua, E0599, hanyalah efek samping dari yang pertama. Perbaiki E0424, dan E0599 ikut hilang.
Apa artinya
Section titled “Apa artinya”Lihat dua label yang ditaruh rustc di kodemu:
- Baris 6:
fn describe()punya tanda kurung kosong. rustc mencatat “this function doesn’t have aselfparameter” (fungsi ini tidak punya parameterself). - Baris 7:
self.namememinta nama “pemain yang memanggil fungsi ini”. Tapidescribetidak pernah diberi pemain, jadiselfdi sini tidak berarti apa-apa.
Fungsi di dalam blok impl yang tidak punya parameter self disebut associated function (fungsi terkait). Fungsi itu milik tipenya (Player::describe()), bukan milik satu nilai tertentu. Fungsi yang punya parameter self disebut method, dan hanya method yang boleh memakai self.
Bayangkan sebuah formulir bertuliskan “tulis namamu sendiri di sini”. Kalimat itu baru masuk akal kalau ada orang yang memegang formulirnya. describe() adalah formulir yang tidak dipegang siapa pun.
Kenapa pesannya bilang “found module self”? Di Rust, self punya arti kedua: modul saat ini, seperti di use self::helpers;. Kalau tidak ada nilai self, rustc memakai arti itu, lalu protes karena modul bukan nilai. Kata “module” bisa kamu abaikan; masalah sebenarnya adalah parameter yang hilang.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Di Rust, tidak ada yang disembunyikan. Java dan C# memberi setiap method non-static sebuah this yang tidak terlihat. Rust memintamu menulis self sebagai parameter pertama, sekaligus menyebutkan bagaimana method itu mendapatkannya: hanya melihat, mengubah, atau mengambil ownership (kepemilikan). Pilihan itu bagian dari aturan borrowing (peminjaman), jadi harus terlihat.
Dengan begitu, semua orang yang membaca kodemu, juga compiler, tahu persis apa yang dilakukan sebuah method terhadap nilainya. fn summary(&self) berjanji tidak mengubah apa pun. fn add(&mut self, ...) memberi tahu bahwa ia mengubah sesuatu. fn checkout(self) menghabiskan nilainya. Lalu compiler memeriksa janji-janji itu untukmu. Method dan blok impl dijelaskan di Struct.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Tambahkan &self, &mut self atau self
Section titled “Perbaikan 1: Tambahkan &self, &mut self atau self”Pilih ini kalau fungsinya memang seharusnya bekerja pada satu nilai yang sudah ada. Hampir selalu inilah perbaikan yang tepat. Tambahkan parameter yang disarankan rustc, lalu panggil dengan titik:
struct Player { name: String,}
impl Player { fn describe(&self) { println!("Pemain: {}", self.name); }}
fn main() { let hero = Player { name: String::from("Ferris") }; hero.describe();}Output:
Pemain: Ferrisrustc selalu menyarankan &self, padahal ada tiga jenis. Pilih yang sesuai dengan apa yang dilakukan method-nya:
| Parameter | Method-nya… | Nama yang umum |
|---|---|---|
&self |
hanya membaca nilainya | summary, len, is_empty, describe |
&mut self |
mengubah nilainya | add, push, reset, level_up |
self |
menghabiskan nilainya (mengambil ownership) | into_..., finish, build, checkout |
Ini ketiganya pada satu tipe:
struct Order { items: Vec<String>,}
impl Order { fn summary(&self) -> String { format!("{} barang: {}", self.items.len(), self.items.join(", ")) }
fn add(&mut self, item: &str) { self.items.push(item.to_string()); }
fn checkout(self) -> Vec<String> { self.items }}
fn main() { let mut order = Order { items: Vec::new() }; order.add("kopi"); order.add("roti"); println!("{}", order.summary()); let packed = order.checkout(); // order habis dipakai di sini println!("Dikemas: {:?}", packed);}Output:
2 barang: kopi, rotiDikemas: ["kopi", "roti"]Kalau kamu memilih &self tapi method-nya mengubah sebuah field, compiler langsung memberi tahu (E0594 “cannot assign to self.count, which is behind a & reference”, atau E0596 untuk pemanggilan seperti push). Ganti dengan &mut self. Kalau ragu, mulai dengan &self; self jarang dipakai.
Perbaikan 2: Panggil sebagai Type::method(&value)
Section titled “Perbaikan 2: Panggil sebagai Type::method(&value)”Begitu sebuah fungsi punya parameter self, kamu bisa memanggilnya dengan dua cara. hero.label() dan Player::label(&hero) artinya persis sama: nilai yang biasanya ada di depan titik menjadi argumen pertama. Bentuk dengan titik yang paling sering kamu tulis. Bentuk Type:: berguna kalau kamu ingin memberikan method itu sendiri ke sesuatu seperti map:
struct Player { name: String, level: u32,}
impl Player { fn label(&self) -> String { format!("{} (level {})", self.name, self.level) }}
fn main() { let hero = Player { name: String::from("Ferris"), level: 3 }; println!("{}", hero.label()); println!("{}", Player::label(&hero)); // pemanggilan yang sama
let team = vec![hero, Player { name: String::from("Corro"), level: 5 }]; let labels: Vec<String> = team.iter().map(Player::label).collect(); println!("{:?}", labels);}Output:
Ferris (level 3)Ferris (level 3)["Ferris (level 3)", "Corro (level 5)"]Yang tidak bisa adalah Player::label() tanpa nilai: sebuah method selalu butuh self-nya. Kalau dilewatkan, kamu mendapat E0061, “this function takes 1 argument but 0 arguments were supplied” (fungsi ini butuh 1 argumen, tapi diberi 0).
Perbaikan 3: Berikan apa yang dibutuhkan fungsinya
Section titled “Perbaikan 3: Berikan apa yang dibutuhkan fungsinya”Pilih ini kalau belum ada nilainya, atau kalau fungsinya sama sekali tidak berada di dalam blok impl.
Contoh klasiknya adalah constructor. new yang membuat nilainya, jadi tidak ada self untuk dibaca. Berikan data awalnya ke new sebagai parameter biasa, lalu buat struct-nya dengan Self { ... }:
struct Counter { count: u32, step: u32,}
impl Counter { fn new(step: u32) -> Self { Self { count: 0, step } }
fn tick(&mut self) { self.count += self.step; }}
fn main() { let mut counter = Counter::new(5); counter.tick(); counter.tick(); println!("Hitungan: {}", counter.count);}Output:
Hitungan: 10Perhatikan huruf besarnya: Self (S besar) adalah tipe, jadi Self { ... } membuat nilai baru. self (s kecil) adalah nilai yang memanggil method itu.
Ide yang sama juga memperbaiki fungsi bebas, yaitu fungsi di luar blok impl mana pun. Di sana rustc memakai kalimat yang sedikit berbeda: “this function can’t have a self parameter” (fungsi ini tidak bisa punya parameter self). Sebagai gantinya, berikan struct-nya lewat referensi:
struct Cart { items: Vec<u32>,}
fn total(cart: &Cart) -> u32 { cart.items.iter().sum()}
// panggil dengan: total(&cart)Atau pindahkan total ke dalam impl Cart dan beri &self, seperti di Perbaikan 1. Dua-duanya boleh; method terasa lebih alami kalau fungsinya jelas “tentang” sebuah keranjang belanja.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Di dalam new. Menulis self.count = 0; di fn new() -> Self menghasilkan E0424, dan saran rustc fn new(&self) -> Self tidak masuk akal (kamu butuh counter untuk membuat counter). Perbaikannya: buat nilainya dengan Self { count: 0 }, seperti di Perbaikan 3.
Di dalam closure pada sebuah associated function. Masalahnya bukan di closure-nya, tapi di fungsi yang membungkusnya:
error[E0424]: expected value, found module `self` --> src/main.rs:8:35 |7 | fn sale_prices(prices: &[u32]) -> Vec<u32> { | ----------- this function doesn't have a `self` parameter8 | prices.iter().map(|p| p - self.discount).collect() | ^^^^ `self` value is a keyword only available in methods with a `self` parameterPerbaikannya: jadikan method, fn sale_prices(&self, prices: &[u32]), atau berikan angkanya sebagai parameter, fn sale_prices(prices: &[u32], discount: u32). Lihat Closure.
Di main atau fungsi bantu. self tidak pernah bisa dipakai di luar blok impl. Perbaikannya: berikan struct-nya sebagai parameter (total(&cart)), atau panggil method pada struct itu (cart.total()).
Datang dari method “static” C# atau Java. Associated function tanpa self adalah versi Rust dari static method. Kalau kamu ingin versi instance-nya, kamu harus menambahkan parameter self sendiri. Lihat Rust untuk developer C#.
Error terkait
Section titled “Error terkait”- E0425: kekeliruan kebalikannya. Kamu ada di dalam method, tapi menulis
count, bukanself.count. - E0599: “no method named … found” (method tidak ditemukan). Sering muncul tepat setelah E0424, karena fungsi tanpa
selftidak bisa dipanggil dengan titik. - E0061: jumlah argumen salah, misalnya memanggil
Player::label()tanpa nilainya. - E0596: kamu sudah menambahkan
&self, tapi method-nya mengubah sebuah field, jadi butuh&mut self. Mengisi field dengan cara ini menghasilkan E0594. - Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Di dalam impl Player, fn heal() { self.hp += 10; } menghasilkan E0424. Apa perbaikan terbaiknya?
2. Kenapa fn new() -> Self tidak bisa memakai self.name?
3. fn label(&self) -> String didefinisikan pada Player. Pemanggilan mana yang sama dengan hero.label()?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0424 — Rust error codes index (bahasa Inggris): penjelasan resmi error ini, dengan contoh singkat.
- Method Syntax — The Rust Book (bahasa Inggris):
&self,&mut selfdanself, ditambah associated function sepertinew. - Associated functions and methods — Rust by Example (bahasa Inggris): contoh yang bisa dijalankan untuk kedua jenis fungsi, berdampingan.
- The
selfkeyword — dokumentasi standard library (bahasa Inggris): kedua artiself, yaitu penerima method dan modul saat ini. - Associated items — The Rust Reference (bahasa Inggris): aturan persisnya untuk method, receiver, dan associated function.