What is going on with `unconstrained generic constants` in Rust?

794 Views Asked by At

I was experimenting with const generics when this strange error came out: error: unconstrained generic constant. What does it mean?

Maybe I should describe what was I tried to do before actual code - I wanted to treat types as numbers, using Lisp-like Cons and Nil.

Here's an example:

use core::marker::PhantomData;

struct Nil;

struct Cons <N> (PhantomData <N>);

So '1' is Cons <Nil>, '2' - Cons <Cons <Nil>>, etc.

Then I tried to implement extracting normal number from this.

trait Len {
    const N: usize;
}

impl <N: Len> Len for Cons <N> {
    const N: usize = 1 + N::N;
}

impl Len for Nil {
    const N: usize = 0;
}

And it works.

Then I started doing actual job: my true task was not to just experiment with generic types, but to implement mathematical vecs, just like(maybe you know) in shaders.

So I tried to implement such powerful constructor:

vec3 i = vec3(1.0, 1.0, 1);
vec4 v = vec4(i);

I have decided to treat any value as 'Piece' and then just compound pieces together.

trait Piece <T> {
    type Size: Len;

    fn construct(self) -> [T; Self::Size::N];
}

No problems so far. Next step is to define few auxiliary traits(since rust does not yet support negative bounds):

pub auto trait NotTuple {}

impl <T> !NotTuple for (T,) {}

pub auto trait NotList {}

impl <T, const N: usize> !NotList for [T; N] {}

I am using nightly rust, so few #![feature]-s is not a problem.

Then, we can use it:

type One = Cons <Nil>;

impl <T: Copy + From <U>, U: Copy + NotTuple + NotList> Piece <T> for U {
    type Size = One;

    fn construct(self) -> [T; Self::Size::N] {
        [T::from(self)]
    }
}

This one constructs piece from an argument.

Everything is still good.

impl <T: Copy, U: Piece <T>> Piece <T> for (U,) {
    type Size = U::Size;

    fn construct(self) -> [T; Self::Size::N] {
        self.0.construct()
    }
}

And this is where problem occurs. Compiler says that Self::Size::N is an unconstrained generic constant, and tries to help with this: try adding a 'where' bound using this expression: 'where [(); Self::Size::N]:', but this is just useless.

Can anyone explain me what is going on and how to fix this issue?

0

There are 0 best solutions below