Tried to allocate array dynamically with const generics (Rust)

Page content

Since v1.51, const generic feature was officially released.

static and const

https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/const-and-static.html

static

Rust provides a ‘global variable’ sort of facility in static items. They’re similar to constants, but static items aren’t inlined upon use. This means that there is only one instance for each value, and it’s at a fixed location in memory.

const

Constants live for the entire lifetime of a program. More specifically, constants in Rust have no fixed address in memory. This is because they’re effectively inlined to each place that they’re used. References to the same constant are not necessarily guaranteed to refer to the same memory address for this reason.

lazy-static

Sometimes I wanted to calculate some value and store it as a static variable BEFORE entering main function.

The standard Rust doesn’t provide such feature, so I need to use lazy_static crate.

macro for declaring lazily evaluated statics in Rust.

Using this macro, it is possible to have statics that require code to be executed at runtime in order to be initialized.

It’s super compact but useful.

Edit: Oct.2.2022

https://www.youtube.com/watch?v=Vw8BFScm0K0

const function could be used for initialization, but as of Oct.2.2022, const function block doesn’t support unwrap.

https://github.com/rust-lang/rust/issues/7493

What are const generics

Const generics are generic arguments that range over constant values, rather than types or lifetimes. This allows, for instance, types to be parameterized by integers.

Sample: Poor implementation of Vector on stack

#[derive(Debug)]
struct StackVector<const N: usize> {
    data: [f64; N],
    size: usize
}

impl<const N: usize> StackVector<N> {
    fn new() -> Self {
        StackVector {
            data: [0. ;N],
            size: N
        }
    }
}

fn main() {
    let x = StackVector::<6>::new();
    println!("{:?}", x);
    // StackVector { data: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], size: 6 }
    // The type is `StackVector<6_usize>`
}

Dynamical sizing?

As a value of const is determined at compile time (because it is inlined), the value of const should be decided at compile time. An user input CAN’T be const.

The following code isn’t compiled:

use std::io;

#[derive(Debug)]
struct StackVector<const N: usize> {
    data: [f64; N],
    size: usize
}

impl<const N: usize> StackVector<N> {
    fn new() -> Self {
        StackVector {
            data: [0. ;N],
            size: N
        }
    }
}

fn main() {
    let nrows: usize;
    let mut input = String::new();
    println!("Input the number of rows:");
    io::stdin()
        .read_line(&mut input)
        .expect("Failed to read line");
    let trimmed = input.trim();
    match trimmed.parse::<usize>() {
        Ok(i) => {
            nrows = i;
        },
        Err(..) => panic!(),
    };
    let x = StackVector::<nrows>::new();
    println!("{:?}", x);
}

Here is the compile error:

error[E0435]: attempt to use a non-constant value in a constant
  --> src/main.rs:33:27
   |
19 |     let nrows: usize;
   |     --------- help: consider using `const` instead of `let`: `const nrows`
...
33 |     let x = StackVector::<nrows>::new();
   |                           ^^^^^ non-constant value

As a work around, I came up with the idea with lazy_static, but there is no compatibility between const and static for const generics. So when you change the type to static, it returns error as follows:

error[E0013]: constants cannot refer to statics
  --> src/main.rs:55:22
   |
55 |     let A = Matrix::<n, m>::new();
   |                      ^
   |
   = help: consider extracting the value of the `static` to a `const`, and referring to that
`

Current restrictions (Feb. 13 2022)

https://blog.rust-lang.org/2021/02/26/const-generics-mvp-beta.html#current-restrictions

  • Only integral types are permitted for const generics
  • No complex generic expressions in const arguments

Other reference