How to get associate const value of an opaque type?

The opaque type is certain. Is it possible to get its associate const value without writing the complete type?

struct Use;
struct Chain<A, B>(A, B);

trait Count {
    const COUNT: usize;
}

impl Count for Use {
    const COUNT: usize = 1;
}

impl<A, B> Count for Chain<A, B>
where
    A: Count,
    B: Count,
{
    const COUNT: usize = A::COUNT + B::COUNT;
}

fn get_array<const N: usize>() -> [u8; N] {
    [0; N]
}

fn main() {
    let complex = Chain(Use, Chain(Use, Use));
    get_array::< /* complex's count */ >();
}

What does opaque type mean in your case?

complex is of the concrete type Chain::<Use, Chain::<Use, Use>> which is not opaque. It means you can pass it to the type parameter:

get_array::<{ Chain::<Use, Chain::<Use, Use>>::COUNT }>();

If you want the compiler to infer the type for you, mock the API of type_name_of_val in std::any - Rust

// requires #![feature(generic_const_exprs)] though
fn get_array_of_value<V: Count>(_: &V) -> [u8; V::COUNT] {
    [0; V::COUNT]
}

Rust Playground

2 Likes

If you can constly construct the value, you can constly get the usize.

(This is working around the lack of TAIT. There may be a better way.)

3 Likes

Sorry I didn't make it clear, yes I mean Chain::<Use, Chain::<Use, Use>>. If the expression is very complex, it is more than hard to write the type manually, so it can considered a opaque type (impl Count). So I think your workaround is not good enough, but thanks.

You probably wish Rust had typeof, like this thread. (Some links within.)

1 Like

Thanks. I modified your workaround to let count_thing to not need to be a constant function.

But I wonder can count_thing be a closure?

1 Like

Only if you can construct it in a const context somehow. (I didn't try.)

If your closure captures no runtime value, then the closure can be a fn -> foo.(There is a problem with this expression, but I can't think of the right way to say it at the moment.)

However, if you want some more complex closures, such as FnMut -> bar, then you need nightly's ~const Trait.

The closure does capture environment values, or there is no difference than fn item. And I need it to be stable not in nightly. Thanks also.