Skip to content

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.)

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);
}

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.

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.

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 days
▶ Try it Yourself

You 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 rounds
▶ Try it Yourself

This 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.

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.00
24.00
▶ Try it Yourself

The 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 cells
▶ Try it Yourself

One 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.

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>();.

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