Penjelasan Error Compiler Rust untuk Pemula
Dapat error merah dari compiler Rust dan bingung apa maunya? Kamu datang ke tempat yang tepat. Semua developer Rust melihat error seperti ini, sering kali berkali-kali dalam sehari. Kabar baiknya: hanya ada sedikit error yang akan kamu temui lagi dan lagi, dan begitu kamu mengenalnya, error itu tidak lagi menakutkan.
Setiap halaman di bawah membahas satu kode error: menunjukkan pesan aslinya, menjelaskannya dengan bahasa sederhana, dan memberi perbaikan yang bisa kamu jalankan langsung di browser. Compiler Rust selalu menulis pesannya dalam bahasa Inggris, jadi di sini kamu akan melihatnya apa adanya, lalu penjelasannya dalam bahasa Indonesia.
Error yang paling sering muncul
Section titled “Error yang paling sering muncul”| Error | Kata compiler | Dengan bahasa sederhana |
|---|---|---|
| E0382 | borrow of moved value | Kamu sudah menyerahkan sebuah nilai, lalu mencoba memakainya lagi |
| E0502 | cannot borrow as mutable because it is also borrowed as immutable | Kamu mengubah sesuatu saat masih ada yang membacanya |
| E0499 | cannot borrow as mutable more than once at a time | Dua bagian kode ingin mengubah hal yang sama sekaligus |
| E0308 | mismatched types | Kamu memberi satu tipe padahal yang diharapkan tipe lain |
| E0277 | the trait bound is not satisfied | Sebuah tipe tidak bisa melakukan yang kamu minta (dicetak, dibandingkan, dijumlahkan…) |
| E0106 | missing lifetime specifier | Rust tidak tahu berapa lama referensi yang dikembalikan tetap valid |
| E0425 | cannot find value in this scope | Sebuah nama salah ketik, atau dipakai di luar blok tempatnya berada |
| E0599 | no method named … found | Method itu tidak ada di tipe tersebut, atau trait-nya belum di-import |
| E0384 | cannot assign twice to immutable variable | Kamu mengubah variabel yang tidak dideklarasikan mut |
| E0596 | cannot borrow as mutable, as it is not declared as mutable | Kamu mencoba mengubah sesuatu lewat variabel atau referensi yang bukan mut |
| E0597 | borrowed value does not live long enough | Sebuah referensi masih dipakai padahal nilai yang ditunjuknya sudah hilang |
| E0515 | cannot return reference to local variable | Kamu mengembalikan referensi ke sesuatu yang dibuang saat fungsi selesai |
| E0373 | closure may outlive the current function, but it borrows … | Sebuah closure (sering kali thread) meminjam variabel lokal yang mungkin sudah hilang sebelum closure berjalan |
| E0369 | binary operation == cannot be applied to type … |
Tipemu (belum) mendukung ==, <, + dan kawan-kawannya |
| E0432 | unresolved import | Sebuah baris use menunjuk ke crate, modul, atau item yang tidak ditemukan |
| E0433 | cannot find type … in this scope (versi lama: failed to resolve) | Path seperti HashMap::new() memakai nama yang belum di-import atau tidak ada |
| E0424 | self value is a keyword only available in methods with a self parameter |
Kamu memakai self di fungsi yang tidak menerima self |
| E0061 | this function takes N arguments but M arguments were supplied | Jumlah argumen yang kamu berikan terlalu banyak atau terlalu sedikit (Rust tidak punya argumen opsional) |
| E0594 | cannot assign to p.hp, as p is not declared as mutable |
Kamu mengubah sebuah field atau nilai di balik & tanpa akses mut |
| E0004 | non-exhaustive patterns: X not covered |
match-mu tidak menangani semua kemungkinan nilai |
| E0507 | cannot move out of x which is behind a shared reference |
Kamu mencoba mengambil ownership dari sesuatu yang hanya kamu pinjam |
| E0603 | function x is private |
Kamu memakai fungsi, struct, atau modul yang bukan pub |
| E0716 | temporary value dropped while borrowed | Kamu menyimpan referensi ke nilai yang dibuang di akhir baris |
| E0463 | can’t find crate for x |
Sebuah crate (atau standard library untuk suatu target) belum terpasang |
| E0368 | binary assignment operation += cannot be applied to type … |
Tipemu tidak mendukung +=, -= dan kawan-kawannya |
| E0057 | this function takes N arguments but M were supplied (note: closure defined here) | Kamu memanggil closure dengan argumen terlalu banyak atau terlalu sedikit |
| E0282 | type annotations needed | Rust tidak bisa menebak sebuah tipe sendiri, jadi kamu perlu menuliskannya |
| E0609 | no field x on type T |
Nama field salah ketik, atau nilainya masih terbungkus (misalnya dalam Option) |
| E0593 | closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments | Sebuah closure menerima argumen terpisah padahal yang diharapkan tuple (atau jumlah argumen yang berbeda) |
| E0631 | type mismatch in closure arguments | Tipe parameter closure tidak cocok dengan yang diterimanya (sering i32 vs &i32) |
| E0005 | refutable pattern in local binding | let Some(x) = … bisa gagal, jadi let biasa tidak menerimanya |
| E0615 | attempted to take value of method len on type String |
Kamu menulis s.len, padahal seharusnya s.len() |
| E0610 | {integer} is a primitive type and therefore doesn’t have fields |
Kamu memakai .field pada angka, bool, atau char |
| E0560 | struct User has no field named nmae |
Struct literal memakai nama field yang tidak dimiliki struct itu |
| E0616 | field balance of struct Account is private |
Kamu membaca field yang bukan pub dari luar modulnya |
| E0451 | field x of struct Y is private |
Kamu membuat struct dengan literal padahal sebagian field-nya private |
| E0624 | method x is private |
Kamu memanggil method atau associated function yang bukan pub |
| E0283 | type annotations needed (cannot infer type … multiple impls satisfy this bound) | Ada beberapa tipe yang cocok (misalnya .collect(), .sum()), jadi kamu harus memilih salah satu |
| E0284 | type annotations needed: cannot satisfy <_ as FromStr>::Err == _ |
"42".parse() tidak tahu harus mengubah teks menjadi tipe apa |
| E0790 | cannot call associated function on trait without specifying the corresponding impl type |
Kamu menulis Default::default() atau Trait::new() tanpa menyebut tipenya |
| E0559 | variant Shape::Circle has no field named r |
Varian enum ditulis dengan nama field yang tidak dimiliki varian itu |
| E0063 | missing field email in initializer of User |
Kamu membuat struct tapi ada satu atau lebih field yang belum diisi |
| E0689 | can’t call method pow on ambiguous numeric type {integer} |
2.pow(10) atau 2.0.sqrt() butuh tipe angka yang konkret, seperti i32 atau f64 |
| E0034 | multiple applicable items in scope | Dua trait memberi tipemu method dengan nama yang sama, jadi Rust tidak bisa memilih |
| E0412 | cannot find type X in this scope (Rust 1.93+ prints E0425) |
Nama tipe salah ketik, belum di-import, atau belum dideklarasikan |
| E0428 | the name area is defined multiple times |
Dua item memakai satu nama yang sama; Rust tidak punya overloading fungsi |
| E0026 | variant Shape::Circle does not have a field named r |
Sebuah pattern menyebut field yang tidak dimiliki struct atau variannya |
| E0027 | pattern does not mention fields id, paid |
Pattern struct melewatkan beberapa field; tambahkan field-nya atau akhiri dengan .. |
| E0533 | expected unit struct, unit variant or constant, found struct variant Shape::Circle |
Varian struct (atau fungsi) dipakai di tempat yang mengharapkan nama biasa; tambahkan { .. } |
| E0592 | duplicate definitions with name reset |
Dua blok impl mendefinisikan method dengan nama yang sama |
| E0255 | the name Error is defined multiple times |
Sebuah import use bernama sama dengan tipe atau fungsi buatanmu sendiri |
| E0252 | the name Result is defined multiple times |
Dua baris use memasukkan nama yang sama; ganti nama salah satunya dengan as |
| E0411 | cannot find type Self in this scope |
Kamu memakai Self di luar impl atau trait |
| E0405 | cannot find trait Display in this scope |
Nama trait salah ketik atau belum di-import (misalnya use std::fmt::Display;) |
| E0532 | expected unit struct, unit variant or constant, found tuple variant Shape::Circle |
Pattern menyebut varian tuple (atau struct) tanpa ( )-nya, atau menambahkan ( ) di tempat yang tidak seharusnya |
| E0164 | expected tuple struct or tuple variant, found struct variant Shape::Circle |
Pattern memakai ( ) pada varian struct atau item asosiasi; pakai { } atau guard |
| E0404 | expected trait, found derive macro Debug |
Kamu menulis impl X for atau T: X padahal X adalah struct, alias, atau derive macro yang belum di-import |
| E0401 | can’t use generic parameters from outer item | fn di dalam fungsi lain memakai T atau Self milik fungsi luarnya; beri generics sendiri atau pakai closure |
| E0107 | enum takes 2 generic arguments but 1 generic argument was supplied | Result<u32>, HashMap<String>, dan sejenisnya: argumen di < > terlalu sedikit atau terlalu banyak |
| E0530 | match bindings cannot shadow tuple variants | Nama varian tanpa tanda kurung seperti Circle => (setelah use Shape::*) tidak bisa menjadi variabel baru |
| E0434 | can’t capture dynamic environment in a fn item | fn di dalam fungsi lain tidak bisa melihat variabel lokal fungsi luarnya; pakai closure atau kirim nilainya sebagai argumen |
| E0601 | main function not found in crate main |
Program binary tidak punya fn main() (tidak ada, salah ketik, ada di dalam mod, atau sebenarnya ini library) |
| E0658 | use of unstable library feature iter_intersperse |
Kamu memakai API khusus nightly di Rust stable; pakai alternatif stabilnya atau update Rust |
| E0614 | type u32 cannot be dereferenced |
Kamu menulis *x padahal x sudah berupa nilai biasa, bukan referensi |
| E0435 | attempt to use a non-constant value in a constant | Sebuah const, panjang array, atau static memakai variabel let; jadikan const atau pakai Vec |
| E0554 | #![feature] may not be used on the stable release channel |
Kode salinan khusus nightly; hapus atributnya dan pakai API stabil, atau pakai nightly dengan sengaja |
Cara membaca error Rust
Section titled “Cara membaca error Rust”Pesan error Rust terkenal sangat membantu, tapi isinya padat. Ini contoh yang asli:
fn main() { let name = String::from("Ferris"); let greeting = name; println!("{name}");}error[E0382]: borrow of moved value: `name` --> src/main.rs:4:16 |2 | let name = String::from("Ferris"); | ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait3 | let greeting = name; | ---- value moved here4 | println!("{name}"); | ^^^^ value borrowed here after move |help: consider cloning the value if the performance cost is acceptable |3 | let greeting = name.clone(); | ++++++++Baca dengan urutan ini:
- Baris pertama adalah ringkasannya: kode error (
E0382) dan deskripsi satu baris. - Baris panah (
--> src/main.rs:4:16) memberi tahu file, baris, dan kolom tempat masalahnya terjadi. - Tanda
^^^^menunjuk tepat ke lokasi error. Tanda----adalah cerita yang mengarah ke sana. Di sini artinya: nilainya dibuat di baris 2, dipindahkan (move) di baris 3, lalu dipakai di baris 4. help:adalah saran perbaikan dari compiler, sering lengkap dengan kode yang perlu ditambahkan (tanda++++menunjukkan karakter baru). Saran ini tidak selalu perbaikan terbaik, tapi titik awal yang bagus.
Mulailah membaca dari error pertama. Satu kesalahan bisa memicu rentetan error lanjutan, dan memperbaiki yang pertama sering membuat sisanya ikut hilang.
Tiga kebiasaan yang membantu
Section titled “Tiga kebiasaan yang membantu”-
Minta penjelasan lebih ke compiler. Setiap kode error punya penjelasan panjang bawaan. Jalankan ini di terminal:
Terminal window rustc --explain E0382Kamu akan mendapat deskripsi singkat, contoh yang rusak, dan contoh yang sudah diperbaiki (dalam bahasa Inggris).
-
Sering-sering cek.
cargo checkmencari error tanpa membangun seluruh program, jadi jauh lebih cepat daripadacargo build. Kalau kamu menjalankannya setiap beberapa baris, kamu menghadapi satu error sekali waktu, bukan dua puluh. Lihat Cargo dan crate. -
Biarkan editor menampilkan error saat kamu mengetik. Dengan ekstensi rust-analyzer, error muncul langsung di kodemu, dengan teks bantuan yang sama. Lihat Tools dan setup Rust.
Kenapa Rust punya begitu banyak error
Section titled “Kenapa Rust punya begitu banyak error”Sebagian besar error ini ada karena Rust memeriksa, sebelum programmu berjalan, hal-hal yang di bahasa lain baru ketahuan saat runtime (atau tidak pernah ketahuan sama sekali): memakai memori yang sudah dibebaskan, dua thread mengubah data yang sama, lupa mengecek null. Setiap error yang kamu perbaiki adalah bug yang tidak akan pernah sampai ke pengguna.
Karena itu banyak orang bilang: di Rust, “pertarungannya” terjadi saat kompilasi, dan setelah itu programnya langsung jalan. Aturan di balik error yang paling umum dibahas di Ownership (kepemilikan), Borrowing (peminjaman), dan Lifetime.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Sebuah error Rust menampilkan beberapa masalah. Mana yang sebaiknya kamu perbaiki dulu?
2. Apa yang dilakukan rustc --explain E0382?
3. Dalam pesan error, apa yang ditunjukkan oleh tanda ^^^^?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- Rust Compiler Error Index (bahasa Inggris): daftar resmi semua kode error, masing-masing dengan contoh yang rusak dan yang sudah diperbaiki.
- Understanding Ownership — The Rust Book (bahasa Inggris): aturan di balik error borrowing dan move yang paling umum.
- Error Handling — The Rust Book (bahasa Inggris): cara Rust menangani error di programmu sendiri (
Resultdanpanic!), bukan hanya error compiler. - What is rustc? — The rustc Book (bahasa Inggris): cara kerja compiler, termasuk flag dan level lint-nya.