How to initialize a Option<T> array in rust?

113 views Asked by At

So I'm trying to implement a simple queue for a no_std environment with no heap allocations like this:

pub struct Queue<T: Sized, const SIZE: usize> {
    pub data: [Option<T>; SIZE],
}

impl<T: Sized, const SIZE: usize> Queue<T, SIZE> {
    pub const fn new() -> Queue<T, SIZE> {
        const DEFAULT: Option<T> = None;
        Queue {
            data: [DEFAULT; SIZE],
        }
    }
}

It seems to me that this should be possible since T is sized and a None value can be const so it can be copied without T having to implement the Copy trait. I cannot seem to figure out how to do it however. The above syntax gives an error with a wonderfully useless tip suggesting I should replace T with T:

error[E0401]: can't use generic parameters from outer function
  --> src/queue.rs:11:31
   |
9  | impl<T: Sized, const SIZE: usize> Queue<T, SIZE> {
   |      - type parameter from outer function
10 |     pub const fn new() -> Queue<T, SIZE> {
11 |         const DEFAULT: Option<T> = Default::default();
   |                      -        ^ use of generic parameter from outer function
   |                      |
   |                      help: try using a local generic parameter instead: `<T>`

Is there any way to achieve this? I'm using the 2021 edition of rust by the way.

2

There are 2 answers

1
Kevin Reid On BEST ANSWER

Associated constants of a type are allowed to use its parameters, so this compiles:

pub struct Queue<T: Sized, const SIZE: usize> {
    pub data: [Option<T>; SIZE],
}

impl<T: Sized, const SIZE: usize> Queue<T, SIZE> {
    const NONE_T: Option<T> = None;

    pub const fn new() -> Queue<T, SIZE> {
        Queue {
            data: [Self::NONE_T; SIZE],
        }
    }
}

(Playground)

It's unfortunate that the constant can't be inside the function, but it can at least be private.

0
Filipe Rodrigues On

If you're using nightly, you can enable the inline_const feature and not even require a const item:

#![feature(inline_const)]

pub struct Queue<T: Sized, const SIZE: usize> {
    pub data: [Option<T>; SIZE],
}

impl<T: Sized, const SIZE: usize> Queue<T, SIZE> {
    pub const fn new() -> Queue<T, SIZE> {
        Queue {
            data: [const { None }; SIZE],
        }
    }
}

(Playground)