1

I am trying to get a better understanding of const generic expressions and I have not been able run the following

trait Foo<const N: usize> {}

impl<const N: usize> Foo<{ N * N }> for () {}

because

the const parameter N is not constrained by the impl trait, self type, or predicates

I have also tried calculating the square root compile time, but


trait Bar<const N: usize> {
    fn bar();
}

impl<const N: usize> Bar<N> for () {
    fn bar() {
        const L: i32 = 1 << N.ilog2();
    }
}

but am running into an issue on N

can't use generic parameters from outer function

I'm not understanding why the first example is failing to compile as Foo is bound by N*N which should resolve to a number.

Saxpy
  • 129
  • 1
  • 7
  • Does `()` implement `Foo<2376927>`? How would the compiler find that out? – kmdreko Mar 19 '23 at 19:45
  • The first part and the second part of your question are completely independent. Which one should we answer? If both are connected, it's not obvious to me how; maybe there is context missing of what you are actually trying to achieve? This smells strongly like an [XY problem](https://en.wikipedia.org/wiki/XY_problem) to me. – Finomnis Mar 19 '23 at 20:15
  • The first one, it’s a good point that you can’t generically implement for for every value of N because of overflow. I’m wondering if there is an alternative because N will realistically not reach those bounds – Saxpy Mar 19 '23 at 20:17
  • @Saxpy *"I’m wondering if there is an alternative"* - To answer this, you need to tell us what you are actually trying to achieve :) – Finomnis Mar 19 '23 at 20:18
  • 1
    Shortly, your problem arises because you can't make generics that are "useless" (ie. that you don't directly use where you declare them). This makes the very first line of your first example fail. Furthermore, the second line of the same example fails because you can't (apparently) use generic constants in part of generic const expressions, except alone, without enabling the feature `generic_const_exprs`, which is incomplete rn. – jthulhu Mar 19 '23 at 21:41
  • @jthulhu the first line is not a problem, and I'm not quite sure the second line isn't only a problem because `generic_const_exprs` isn't fully implemented yet [because this is totally valid](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=b83fd5094f2b924db46075d5ddefd0b7) – cafce25 Mar 20 '23 at 00:37

1 Answers1

2

First of all expressions in const generic places are only allowed with a nightly compiler and #![feature(generic_const_exprs)] enabled, but even with that it still won't quite compile.

It's quite likely that generics which only appear in expressions will never be considered constrained because with arbitrary expressions the imposed constraints might be impossible or very hard to calculate.

The expanded explanation for E0207 isn't that helpful for this concrete example etiher cause it doesn't talk about expressions at all.

You can still sort of implement something like that by simply passing a second const generic as a dummy which directly receives the generic of the impl:

#![feature(generic_const_exprs)]
trait Bar<const N: usize, const M: usize> {
}

impl<const N: usize> Bar<N, {N*N}> for () {}

// just for demonstration purposes
fn print_bars<const N: usize, const M: usize>(_: impl Bar<N, M>) {
    println!("{N} {M}");
}

fn main() {
    print_bars::<2, 4>(());
    // print_bars::<2, 2>(()); // does not compile cause obviously this is not implemented by the above
}
cafce25
  • 15,907
  • 4
  • 25
  • 31