1

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?

kmdreko
  • 42,554
  • 6
  • 57
  • 106
Doubtful
  • 83
  • 5
  • Please mention all the nightly features you are using. – trent Dec 14 '21 at 07:03
  • @trent ᶠᵒʳᵐᵉʳˡʸ ᶜˡ generic_const_exprs, auto_traits, negative_impls. Last two can be easily omitted just by replacing `auto` trait to something else. – Doubtful Dec 14 '21 at 07:06
  • 4
    Rust's `generic_const_exprs` feature is *incomplete*, and far from it if I understand correctly, so we should temper our expectations. The current [solution](https://github.com/rust-lang/rust/issues/79778) should be to specify `where [(); Self::Size::N]:` (yes, blank on the right) as suggested, but that surfaces a "cycle detected when building an abstract representation" error. Perhaps you can bring this case to the Rust team. – kmdreko Dec 14 '21 at 07:07
  • @kmdreko Ah, so sad(. OK, I'll follow your advice, but it can take months before it become possible to do what I want to do. – Doubtful Dec 14 '21 at 07:14
  • 1
    People should be aware that nightly is not a regular way to use Rust, it's basically a beta testing program for compiler/stdlib development. Errors noticed while using it should probably be reported in github tickets rather than on StackOverflow. I don't mean to single out the OP here; lately I've noticed an influx of devs who (with the best of intentions) attempt to use nightly Rust as if it were stable. It's not, and in some cases nightly features can go unstabilized for years, or even end up never getting stabilized. The use of nightly to get work done should be discouraged. – user4815162342 Dec 14 '21 at 08:56

0 Answers0