Rust Error E0435: Attempt to Use a Non-Constant Value in a Constant
E0435 means: something that must be known while your program is being compiled is trying to use a value that only exists while it runs. The usual place is an array length, like [0.0; days], or a const that reads a let variable. The code looks perfectly reasonable, and in many languages it would work. In Rust, constants and array lengths are worked out by the compiler, before the program ever starts, so they can’t look at ordinary variables. It’s a very common error, and the fix is usually one word. (This page is part of Rust compiler errors explained.)
The error message
Section titled “The error message”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; |This is the program that produces it:
fn main() { let days = 7; let rainfall = [0.0; days]; // ❌ an array's length must be known at compile time println!("{:?}", rainfall);}What it means
Section titled “What it means”The ^^^^ points at days on line 3, inside [0.0; days]. That’s the “repeat” form of an array: seven copies of 0.0. The part after the ; is the array’s length, and the length is part of the array’s type: [f64; 7] and [f64; 8] are two different types. So rustc has to know the number while it compiles.
But days is a let variable. To rustc, a let is a value that exists only while the program runs, even when you wrote a plain 7 next to it. “Non-constant value” means exactly that.
The help: shows the fix: turn line 2 into a const. Note the /* Type */ placeholder: a const always needs its type written out, so you’ll write const DAYS: usize = 7;.
The same headline appears when a const or static reads a let variable, like const PRICE_WITH_TAX: f64 = base_price * 1.2;. Then the help: suggests the opposite direction: use let instead of const.
It’s like printing a form. The number of boxes on the form is decided at the print shop, before anyone fills it in. You can’t make the number of boxes depend on an answer someone writes on the form later.
Why Rust does this
Section titled “Why Rust does this”Rust has two moments: compile time, when cargo build turns your code into a program, and run time, when the program runs. A const, a static, and the length of an array are all decided at compile time. The compiler writes them straight into the program. That’s why they’re fast and why they can be used anywhere.
A let variable belongs to run time. Its value can come from a file, from user input, or from a calculation that only happens when the code runs. Rust doesn’t make an exception for let days = 7; just because this one happens to be a literal: the rule stays simple, and your code doesn’t break the day you change 7 to read_days_from_config().
So the question to ask is: do I know this number when I write the code? If yes, make it a const. If no, it can’t be an array length, and a Vec is the right tool. See Constants and Arrays vs vectors.
How to fix it
Section titled “How to fix it”Fix 1: Make the size a const
Section titled “Fix 1: Make the size a const”Choose this when the number is fixed in your code, like the 7 days of a week. Do what the help: says, with two small changes: write the type (usize for a length) and use an UPPER_CASE name, which is the Rust style for constants:
const DAYS: usize = 7; // ✅ known at compile time
fn main() { let mut rainfall = [0.0; DAYS]; rainfall[2] = 4.5; rainfall[5] = 1.0; println!("{:?}", rainfall); println!("{} days", rainfall.len());}Output:
[0.0, 0.0, 4.5, 0.0, 0.0, 1.0, 0.0]7 daysYou can put the const inside main too, right where the let was. At the top of the file, every function can use it. If you keep the lowercase name days, it still compiles, but with a warning that constants should be upper case.
Fix 2: Use a Vec when the size is only known at runtime
Section titled “Fix 2: Use a Vec when the size is only known at runtime”Choose this when the number comes from the running program: the length of a list, a value from a file, user input, a function parameter. Arrays have a fixed size; a Vec is the growable list that can have any size. vec![value; n] is the same “repeat” form, and here n can be any variable:
fn main() { let players = ["Ana", "Ben", "Chen"]; let rounds = players.len() * 2;
let mut scores = vec![0; rounds]; // ✅ a Vec's length can come from a variable scores[0] = 10; scores[3] = 7; println!("{:?}", scores); println!("{} rounds", scores.len());}Output:
[10, 0, 0, 7, 0, 0]6 roundsThis is the right fix far more often than people expect. A Vec works almost everywhere an array does: indexing, .len(), loops, slices (&scores[1..3]). The difference in speed is tiny for normal programs. See Vectors.
Fix 3: Use let instead of const
Section titled “Fix 3: Use let instead of const”Choose this when a const (or static) reads a let variable. This version of the error looks like this:
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`The broken program:
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);}If the value is computed while the program runs, it’s a normal variable, so make it a let (with a lowercase name). If both values really are fixed, the other way works too: make the first one a const as well. Both are shown here:
const BASE_PRICE: f64 = 20.0;const PRICE_WITH_TAX: f64 = BASE_PRICE * 1.2; // ✅ a const can use another const
fn main() { let base_price = 35.0; let price_with_tax = base_price * 1.2; // ✅ a let can use anything println!("{:.2}", price_with_tax); println!("{:.2}", PRICE_WITH_TAX);}Output:
42.0024.00The help: line suggests let PRICE_WITH_TAX; that compiles, but you’ll get a warning that variables should be snake_case. Rename it to price_with_tax.
Fix 4: Const generics or a const fn, when you really need an array
Section titled “Fix 4: Const generics or a const fn, when you really need an array”Choose this when you want a real fixed-size array, but the size should come from outside a function, or be calculated. A function parameter is a runtime value too, so this gives E0435 (rustc says the parameter would need to be a 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 | ^^^^The broken program:
fn empty_row(size: usize) { let row = [0u8; size]; // ❌ `size` is only known when the function runs println!("{:?}", row);}
fn main() { empty_row(3);}A const generic does what rustc asks: <const N: usize> makes the size a compile-time parameter, written empty_row::<5>() or worked out from the type. A const fn is a function the compiler can run at compile time, so you can use it to calculate a constant:
fn empty_row<const N: usize>() -> [u8; N] { [0; N] // ✅ N is a compile-time parameter}
const fn cells(width: usize, height: usize) -> usize { width * height}
const WIDTH: usize = 4;const HEIGHT: usize = 3;const CELLS: usize = cells(WIDTH, HEIGHT); // ✅ computed by the compiler
fn main() { let row: [u8; 3] = empty_row(); let wide = empty_row::<5>(); println!("{:?}", row); println!("{:?}", wide);
let board = [0u8; CELLS]; println!("{} cells", board.len());}Output:
[0, 0, 0][0, 0, 0, 0, 0]12 cellsOne limit on stable Rust: inside a generic function you can use N on its own as a length, but not a calculation with it, like [u8; N * 2]. That gives generic parameters may not be used in const operations and needs a nightly-only feature. If you’re the one calling empty_row(size) with a runtime size, go back to Fix 2. See Generics.
Where you’ll usually see it
Section titled “Where you’ll usually see it”A size from .len() or user input. let n = names.len(); let done = [false; n]; gives E0435, because n is only known at runtime. Fix: let done = vec![false; n]; (Fix 2).
A static that reads a let. static LINE_WIDTH: usize = width; gives the same headline, with help: consider using `let` instead of `static` . A static is decided at compile time just like a const. Fix: use let, or make width a const too.
A const inside a generic function. In fn bytes<T>() -> usize { const SIZE: usize = std::mem::size_of::<T>(); SIZE }, the const can’t use T. That’s a different code, E0401, and the fix is the same idea: let size = std::mem::size_of::<T>();.
Related errors
Section titled “Related errors”- E0434: can’t capture dynamic environment in a fn item: the same “items can’t see local variables” rule, for a
fnwritten inside another function. - E0401: can’t use generic parameters from outer item: a nested
fnorconstthat uses the outer function’sT. - E0015:
cannot call non-const function `args` in constants, when aconstcalls a normal function likestd::env::args()instead of reading a variable. Fix:let, or aconst fn. - E0308: mismatched types: what you get after Fix 1 if an array of the wrong length goes where
[f64; DAYS]is expected. - E0658: use of unstable feature: if you reach for nightly-only const features to get around this.
- All compiler errors explained
Quick check
Section titled “Quick check”Quick check
1. Why does let n = 3; let a = [0; n]; give E0435, even though n is clearly 3?
2. The size of your list comes from a file the program reads. What's the right fix?
3. Which line compiles?
Score: 0 / 3
Read more
Section titled “Read more”- E0435 — Rust error codes index: the official explanation, with the
constfix. - Constants — The Rust Book: how
constdiffers fromlet, and why constants need a type. - Constant evaluation — The Rust Reference: exactly which expressions the compiler can work out at compile time, and where they’re required (array lengths,
const,static). - Storing Lists of Values with Vectors — The Rust Book: the growable list to use when the size is only known at runtime.
- Const generics MVP — Rust Blog: how
<const N: usize>works, with array examples, and what stable Rust can and can’t do with it.