Error Rust E0435: attempt to use a non-constant value in a constant (nilai non-konstan)
E0435 artinya: sesuatu yang harus sudah diketahui saat programmu di-compile mencoba memakai nilai yang baru ada saat program berjalan. Tempat yang paling sering adalah panjang array, seperti [0.0; days], atau sebuah const yang membaca variabel let. Kodenya kelihatan wajar sekali, dan di banyak bahasa lain kode seperti itu jalan. Di Rust, konstanta dan panjang array dihitung oleh compiler, sebelum program dimulai, jadi keduanya tidak bisa melihat variabel biasa. Error ini sangat umum, dan perbaikannya biasanya cuma satu kata. (Halaman ini bagian dari Penjelasan error compiler Rust.)
Pesan error-nya
Section titled “Pesan error-nya”error[E0435]: attempt to use a non-constant value in a constant --> src/main.rs:3:26 |3 | let rainfall = [0.0; days]; // ❌ an array's length must be known at compile time | ^^^^ non-constant value |help: consider using `const` instead of `let` |2 - let days = 7;2 + const days: /* Type */ = 7; |Artinya: ada percobaan memakai nilai non-konstan di dalam konstanta, dan rustc menyarankan memakai const alih-alih let.
Ini program yang menghasilkan error tersebut:
fn main() { let days = 7; let rainfall = [0.0; days]; // ❌ an array's length must be known at compile time println!("{:?}", rainfall);}Apa artinya
Section titled “Apa artinya”Tanda ^^^^ menunjuk ke days di baris 3, di dalam [0.0; days]. Itu bentuk “ulang” sebuah array: tujuh salinan 0.0. Bagian setelah ; adalah panjang array, dan panjang itu bagian dari tipe array-nya: [f64; 7] dan [f64; 8] adalah dua tipe yang berbeda. Jadi rustc harus tahu angkanya saat meng-compile.
Tapi days adalah variabel let. Bagi rustc, let adalah nilai yang hanya ada saat program berjalan, bahkan kalau kamu menulis 7 biasa di sebelahnya. “Non-constant value” (nilai non-konstan) artinya persis itu.
Baris help: menunjukkan perbaikannya: ubah baris 2 menjadi const. Perhatikan placeholder /* Type */: sebuah const selalu butuh tipe yang ditulis, jadi kamu akan menulis const DAYS: usize = 7;.
Judul error yang sama muncul kalau sebuah const atau static membaca variabel let, seperti const PRICE_WITH_TAX: f64 = base_price * 1.2;. Kali ini help:-nya menyarankan arah sebaliknya: pakai let alih-alih const.
Ibaratnya mencetak formulir. Jumlah kotak di formulir ditentukan di percetakan, sebelum ada yang mengisinya. Kamu tidak bisa membuat jumlah kotaknya bergantung pada jawaban yang nanti ditulis seseorang di formulir itu.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Rust punya dua momen: compile time (waktu kompilasi), saat cargo build mengubah kodemu menjadi program, dan runtime (waktu berjalan), saat program dijalankan. const, static, dan panjang array semuanya ditentukan saat compile time. Compiler menuliskannya langsung ke dalam program. Itulah sebabnya semuanya cepat dan bisa dipakai di mana saja.
Variabel let milik runtime. Nilainya bisa datang dari file, dari input pengguna, atau dari perhitungan yang baru terjadi saat kodenya berjalan. Rust tidak membuat pengecualian untuk let days = 7; hanya karena kebetulan isinya literal: aturannya tetap sederhana, dan kodemu tidak tiba-tiba rusak saat suatu hari kamu mengganti 7 dengan read_days_from_config().
Jadi pertanyaan yang perlu kamu ajukan: apakah aku sudah tahu angka ini saat menulis kodenya? Kalau ya, jadikan const. Kalau tidak, angka itu tidak bisa jadi panjang array, dan Vec adalah alat yang tepat. Lihat Konstanta dan Array vs vektor.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Jadikan ukurannya const
Section titled “Perbaikan 1: Jadikan ukurannya const”Pilih ini kalau angkanya tetap di kodemu, seperti 7 hari dalam seminggu. Lakukan apa yang dikatakan help:, dengan dua perubahan kecil: tulis tipenya (usize untuk panjang) dan pakai nama UPPER_CASE, gaya Rust untuk konstanta:
const DAYS: usize = 7; // ✅ sudah diketahui saat compile time
fn main() { let mut rainfall = [0.0; DAYS]; rainfall[2] = 4.5; rainfall[5] = 1.0; println!("{:?}", rainfall); println!("{} hari", rainfall.len());}Output:
[0.0, 0.0, 4.5, 0.0, 0.0, 1.0, 0.0]7 hariKamu juga bisa menaruh const-nya di dalam main, tepat di tempat let tadi. Kalau di bagian atas file, semua fungsi bisa memakainya. Kalau kamu tetap memakai nama huruf kecil days, kodenya tetap ter-compile, tapi dengan warning bahwa konstanta seharusnya ditulis dengan huruf besar.
Perbaikan 2: Pakai Vec kalau ukurannya baru diketahui saat runtime
Section titled “Perbaikan 2: Pakai Vec kalau ukurannya baru diketahui saat runtime”Pilih ini kalau angkanya datang dari program yang sedang berjalan: panjang sebuah daftar, nilai dari file, input pengguna, parameter fungsi. Array punya ukuran tetap; Vec (vektor) adalah daftar yang bisa bertambah dan boleh berukuran berapa saja. vec![value; n] adalah bentuk “ulang” yang sama, dan di sini n boleh variabel apa pun:
fn main() { let players = ["Ana", "Ben", "Chen"]; let rounds = players.len() * 2;
let mut scores = vec![0; rounds]; // ✅ panjang Vec boleh berasal dari variabel scores[0] = 10; scores[3] = 7; println!("{:?}", scores); println!("{} ronde", scores.len());}Output:
[10, 0, 0, 7, 0, 0]6 rondePerbaikan ini jauh lebih sering tepat daripada yang orang kira. Vec bisa dipakai hampir di mana pun array bisa dipakai: indexing, .len(), perulangan, slice (&scores[1..3]). Beda kecepatannya sangat kecil untuk program biasa. Lihat Vektor.
Perbaikan 3: Pakai let alih-alih const
Section titled “Perbaikan 3: Pakai let alih-alih const”Pilih ini kalau sebuah const (atau static) membaca variabel let. Versi error-nya seperti ini:
error[E0435]: attempt to use a non-constant value in a constant --> src/main.rs:3:33 |3 | const PRICE_WITH_TAX: f64 = base_price * 1.2; // ❌ a `const` can't read a `let` variable | ^^^^^^^^^^ non-constant value |help: consider using `let` instead of `const`Artinya: base_price adalah nilai non-konstan, dan rustc menyarankan memakai let alih-alih const. Program yang rusak:
fn main() { let base_price = 20.0; const PRICE_WITH_TAX: f64 = base_price * 1.2; // ❌ a `const` can't read a `let` variable println!("{:.2}", PRICE_WITH_TAX);}Kalau nilainya dihitung saat program berjalan, itu variabel biasa, jadi jadikan let (dengan nama huruf kecil). Kalau kedua nilai memang tetap, arah sebaliknya juga bisa: jadikan yang pertama const juga. Keduanya ditunjukkan di sini:
const BASE_PRICE: f64 = 20.0;const PRICE_WITH_TAX: f64 = BASE_PRICE * 1.2; // ✅ const boleh memakai const lain
fn main() { let base_price = 35.0; let price_with_tax = base_price * 1.2; // ✅ let boleh memakai apa saja println!("{:.2}", price_with_tax); println!("{:.2}", PRICE_WITH_TAX);}Output:
42.0024.00Baris help: menyarankan let PRICE_WITH_TAX; itu ter-compile, tapi kamu akan mendapat warning bahwa nama variabel seharusnya snake_case. Ganti namanya menjadi price_with_tax.
Perbaikan 4: Const generics atau const fn, kalau kamu benar-benar butuh array
Section titled “Perbaikan 4: Const generics atau const fn, kalau kamu benar-benar butuh array”Pilih ini kalau kamu ingin array berukuran tetap yang sungguhan, tapi ukurannya harus datang dari luar sebuah fungsi, atau harus dihitung. Parameter fungsi juga nilai runtime, jadi ini memberi E0435 (rustc bilang parameternya would need to be a const, yaitu seharusnya berupa const):
error[E0435]: attempt to use a non-constant value in a constant --> src/main.rs:2:21 |1 | fn empty_row(size: usize) { | ---- this would need to be a `const`2 | let row = [0u8; size]; // ❌ `size` is only known when the function runs | ^^^^Program yang rusak:
fn empty_row(size: usize) { let row = [0u8; size]; // ❌ `size` is only known when the function runs println!("{:?}", row);}
fn main() { empty_row(3);}Const generic melakukan apa yang diminta rustc: <const N: usize> menjadikan ukurannya parameter compile time, ditulis empty_row::<5>() atau disimpulkan dari tipenya. const fn adalah fungsi yang bisa dijalankan compiler saat compile time, jadi kamu bisa memakainya untuk menghitung sebuah konstanta:
fn empty_row<const N: usize>() -> [u8; N] { [0; N] // ✅ N adalah parameter compile time}
const fn cells(width: usize, height: usize) -> usize { width * height}
const WIDTH: usize = 4;const HEIGHT: usize = 3;const CELLS: usize = cells(WIDTH, HEIGHT); // ✅ dihitung oleh compiler
fn main() { let row: [u8; 3] = empty_row(); let wide = empty_row::<5>(); println!("{:?}", row); println!("{:?}", wide);
let board = [0u8; CELLS]; println!("{} sel", board.len());}Output:
[0, 0, 0][0, 0, 0, 0, 0]12 selSatu batasan di Rust stable: di dalam fungsi generic kamu bisa memakai N begitu saja sebagai panjang, tapi tidak perhitungan dengannya, seperti [u8; N * 2]. Itu memberi generic parameters may not be used in const operations dan butuh fitur yang hanya ada di nightly. Kalau kamulah yang memanggil empty_row(size) dengan size dari runtime, kembali ke Perbaikan 2. Lihat Generics.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Ukuran dari .len() atau input pengguna. let n = names.len(); let done = [false; n]; memberi E0435, karena n baru diketahui saat runtime. Perbaikannya: let done = vec![false; n]; (Perbaikan 2).
static yang membaca let. static LINE_WIDTH: usize = width; memberi judul error yang sama, dengan help: consider using `let` instead of `static` . static ditentukan saat compile time, sama seperti const. Perbaikannya: pakai let, atau jadikan width sebuah const juga.
const di dalam fungsi generic. Di fn bytes<T>() -> usize { const SIZE: usize = std::mem::size_of::<T>(); SIZE }, const-nya tidak bisa memakai T. Itu kode yang berbeda, E0401, dan perbaikannya idenya sama: let size = std::mem::size_of::<T>();.
Error terkait
Section titled “Error terkait”- E0434: can’t capture dynamic environment in a fn item: aturan yang sama, “item tidak bisa melihat variabel lokal”, untuk
fnyang ditulis di dalam fungsi lain. - E0401: can’t use generic parameters from outer item:
fnatauconstbersarang yang memakaiTmilik fungsi luarnya. - E0015:
cannot call non-const function `args` in constants, saat sebuahconstmemanggil fungsi biasa sepertistd::env::args()alih-alih membaca variabel. Perbaikannya:let, atauconst fn. - E0308: mismatched types: yang kamu dapat setelah Perbaikan 1 kalau array dengan panjang yang salah dipakai di tempat yang mengharapkan
[f64; DAYS]. - E0658: use of unstable feature: kalau kamu mencoba fitur const khusus nightly untuk mengakali error ini.
- Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Kenapa let n = 3; let a = [0; n]; memberi E0435, padahal n jelas bernilai 3?
2. Ukuran daftarmu berasal dari file yang dibaca program. Apa perbaikan yang tepat?
3. Baris mana yang bisa ter-compile?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0435 — Rust error codes index (bahasa Inggris): penjelasan resmi, dengan perbaikan memakai
const. - Constants — The Rust Book (bahasa Inggris): beda
constdenganlet, dan kenapa konstanta butuh tipe. - Constant evaluation — The Rust Reference (bahasa Inggris): ekspresi apa saja yang bisa dihitung compiler saat compile time, dan di mana ekspresi itu wajib (panjang array,
const,static). - Storing Lists of Values with Vectors — The Rust Book (bahasa Inggris): daftar yang bisa bertambah, untuk dipakai kalau ukurannya baru diketahui saat runtime.
- Const generics MVP — Rust Blog (bahasa Inggris): cara kerja
<const N: usize>, dengan contoh array, dan apa yang bisa dan tidak bisa dilakukan Rust stable dengannya.