Dealing with no use of Self in const array in a trait

I'd like to use a const usize value associated with a trait to size an array that is also associated with the trait. Unfortunately you cannot perform a const operation using Self, such as:

enum SomeEnum { A, B, C, D, E, F }

trait OriginalGoal {
    const SIZE: usize;
    const DESIRED_ARRAY: [SomeEnum; Self::SIZE];
}

But I have found a workaround using nightly and generic const expressions, though it must be split between two separate traits otherwise the compiler can't reason past the circular dependency...

#![feature(generic_const_exprs)]

trait ArraySize {
    const SIZE: usize;
}

trait DesiredTrait: ArraySize
where
    [SomeEnum; <Self as ArraySize>::SIZE]: Sized,
{
    const DESIRED_ARRAY: [SomeEnum; <Self as ArraySize>::SIZE];
}

This doesn't actually lead to terrible implementations, but the setup is still a bit rough.

struct Test {}

impl ArraySize for Test {
    const SIZE: usize = 3;
}

impl DesiredTrait for Test {
    const DESIRED_ARRAY: [SomeEnum; <Self as ArraySize>::SIZE] = {
        [SomeEnum::A, SomeEnum::B, SomeEnum::F]
    };
}

And a playground link, just to show it working.

I realize I'm just eliminating an associated type by switching to const generics: other playground. But I'm seeing the const generic option as directly allowing methods to return same-sized arrays of other types without defining extra types, as well as being able to define type aliases that rely on said const value:

trait GetFloat: DesiredTrait
where
    [f64; <Self as ArraySize>::SIZE]: Sized,
{
    fn get_float(&self) -> [f64; <Self as ArraySize>::SIZE];
}

type AssociatedArray<D: ArraySize> = [(); <D as ArraySize>::SIZE];

And yet, I wonder if I'm just adding complication for minimal benefit or to get options which I could make work in other ways using associated types.

Does anyone have any thoughts on pros/cons of either method?

Faced with the same limitation, and it pisses me off, =( What the point in const if there are no const?
Any way to do this is stable rust?

trait Foo {
    const LEN: usize;

    fn gen_keys(&self) -> SmallVec<[String; Self::LEN]>;

    fn calculate_hashes(&self) -> SmallVec<[u64; Self::LEN]> {
        self.gen_keys().iter().map(|v| v.len() as u64).collect()
    }
}

struct Bar {}
impl Foo for Bar {
    const LEN: usize = 10;

    fn gen_keys(&self) -> SmallVec<[String; Self::LEN]> {
        smallvec!["1".to_owned(), "2".to_owned(), "3".to_owned()]
    }
}

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.