Attempt to use a non-constant value in a constant?

fn main(){
  let a = vec![1,2,3,4];
  let n: usize = a.len();
  let mut b:[i32; n] = [0; n];      //warn: attempt to use a non-constant value in a constant. why ??
}

why warn: attempt to use a non-constant value in a constant,
before define the "b", the "n" is determined.
how to code to avoid this warning?

Rust is statically typed, and the type of an array ([T; N]) includes its length (N). So N must be a constant value known at compile-time.

You can't perform allocation at compile-time,

  • so you can't create the Vec at compile-time,
  • so you can't query it's length at compile-time,
  • so you can't base the length of the array on the length of the Vec.

What to do instead depends on your use-case, which I can't guess based on this sample code. What's the end goal?

2 Likes

Simply speaking, the way you have formulated the problem, it is impossible to avoid the error. You have the length of an array defined in terms of the length of a vector. However, the length of a vector is known only at runtime, while the length of an array must be known at compile-time. Hence the conflict.

Here is a somewhat similar program which does compile:

fn main() {
    const A: &[i32] = &[1, 2, 3, 4];
    const N: usize = A.len();

    let a = A.to_vec();
    let mut b: [i32; N] = [0; N];
}

Here, N is a constant, and not only that, can be a constant because A is a constant and therefore can have its length taken at compile time. (There are some possible variations on this; for example, A could be an array, but then you'd have to write out its length, defeating the possible goal of getting the length solely from the [1, 2, 3, 4] literal.)

what I want to do is to convert a Vec<Vec> (here for example i32, actually I define a struct for there) to a [[i32; M]; N]

fn main(){
  let a = vec![[1,3,5], [1,6,2], [9,1,2], [8,4,2]];
  
  //convert to:
  let mut b: [[i32;3];4] = [[1,3,5], [1,6,2], [9,1,2], [8,4,2]];
  // the reason why I want to convert to b , because this type have the const length, 
  //in other places I can use it to constrain some variables, and to avoid panics.
}

A Vec<[i32; 3]> (as in your latest code) or a Vec<Vec<i32>>?

3 Likes

If you know the dimensions at compile time, why not use a [i32; M]; N] in the first place and skip the Vec<Vec>> dance?

it's a long procedure and at this point I just get the Vec<Vec>, but the size is M*N.
I will rethink the whole procedure to avoid this..thanks.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.