Recursive constant structure

Does anyone have any ideas how to create a recursive constant structure, where each next level is a brand new constants?
That is, inside the structure there is a constant array and a pointer to the next structure, but with different constant size / bounds, etc.

For clarity, here is an example of the desired code, but unfortunately it does not work (Rust Playground):

pub trait Zeros {
    fn zeros() -> Self;
}

impl<T: Default + Copy, const N: usize> Zeros for [T; N] {
    fn zeros() -> Self {
        [T::default(); N]
    }
}

pub trait Num: Sized {
    const VAL: usize;
}

pub struct Const<const R: usize>;

impl<const T: usize> Num for Const<T> {
    const VAL: usize = T;
}

pub struct Layer<R: Num, C: Num>
where
    [(); R::VAL]: Sized,
    [(); C::VAL]: Sized,
{
    array: Box<[[f32; R::VAL]; C::VAL]>,
    next: Option<Box<Layer<R, C>>>,
}

fn main() {
    // This work
    let layer: Layer<Const<3>, Const<3>> = Layer {
        array: Box::new(Zeros::zeros()),
        next: Some(Box::new(Layer::<Const<3>, Const<3>> {
            array: Box::new(Zeros::zeros()),
            next: None,
        })),
    };

    // But this one doesn't work
    //
    // let layer: Layer<Const<3>, Const<3>> = Layer {
    //     array: Box::new(Zeros::zeros()),
    //     next: Some(Box::new(Layer::<Const<2>, Const<2>> {
    //         array: Box::new(Zeros::zeros()),
    //         next: None,
    //     })),
    // };
}

The sort of "type hiding" you appear to want just isn't a thing (at least, not for static types). Having the constants be part of the type means that the root Layer's type must include all the constants you're going to use for all layers. Since Rust doesn't have variadic generics, you can use something like a cons list:


pub struct Layer<R: Num, C: Num, Next>
where
    [(); R::VAL]: Sized,
    [(); C::VAL]: Sized,
{
    array: Box<[[f32; R::VAL]; C::VAL]>,
    next: Next,
}

fn main() {
    // This work
    let layer: Layer<
        Const<3>, Const<3>,
        Box<Layer<
            Const<2>, Const<2>,
            ()
        >>
    > = Layer {
        array: Box::new(Zeros::zeros()),
        next: Box::new(Layer {
            array: Box::new(Zeros::zeros()),
            next: (),
        }),
    };

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.