Concatenate const generic. Does it have a chance of being possible?

I was wondering if something like this is even remotely possible, or maybe possible in the future?

code

#![feature(generic_const_exprs)]
#![feature(adt_const_params)]

pub struct Foo<const ARR: &'static [usize]>{}
trait Concat<const ARR: &'static [usize]>{
    type Output;
    fn concat(self, other: Foo<ARR>)->Self::Output;
}

impl <const ARR1: &'static [usize], const ARR2: &'static [usize]>Concat<ARR1> for Foo<ARR2>
{
    type Output = Foo<{concat(ARR1, ARR2)}>;
    fn concat(self, other: Foo<ARR1>)->Self::Output {
        Foo{}
    }
}

fn main() {
    let foo = Foo::<{ &[0, 1, 2] }> {};
    let foo2 = Foo::<{ &[3, 4, 5] }> {};
    //let bar: Foo<{&[0, 1, 2, 3, 4, 5]}> = foo.concat(foo2);
}

I found this reddit thread where they kind of manage to concatenate two slices using a macro in a "const way", but it requires creating derivative const which makes it not usable as const parameters (at least is what I understand).

That being said, If possible it would allow some really cool things like checking the dimensions of matrices or tensor operations at compile time.

Hmm, I can achieve something similar with the array-concat crate right now. Would that fit your use-case or am I missing an intricacy of what you want to achieve? Anyway here's how I'd do something that looks similar (to me) to what you are trying to do:

#![feature(adt_const_params)]

use array_concat::*;

pub struct Foo<const ARR: &'static [usize]> {}

impl<const ARR: &'static [usize]> Foo<ARR> {
    fn arr(&self) -> &'static [usize] {
        ARR
    }
}

fn main() {
    const A: [usize; 3] = [1, 2, 3];
    const B: [usize; 3] = [4, 5, 6];
    const C: [usize; concat_arrays_size!(A, B)] = concat_arrays!(A, B);

    let bar = Foo::<{ &C }> {};

    assert_eq!(bar.arr(), [1, 2, 3, 4, 5, 6]);
}

Yes that works if you declare the const C as dependent on const A and B but independent of Foo. But what I'm trying to do is to create Foo<C> from Foo<A> and Foo<B>; if you try that approach it would required to use an associated constant. Something like this, that I think is not possible.

impl <const ARR1: &'static [usize], const ARR2: &'static [usize]>Concat<ARR1, ARR2> for Foo<ARR2>
{
   const A: [usize; concat_arrays_size!(ARR1, ARR2)] = concat_arrays!(ARR1, ARR2);
    fn concat(self, other: Foo<ARR1>)->Foo<A> {
        Foo{}
    }
}

You are right. Unfortunately you can't use generics from the outer function inside the function for a binding. I.e:

fn foo<const N: usize>() {
    const M: usize = N;
}

raises an E0401.

Maybe this will become available in const { ... } blocks when inline_const is stabilized. According to the PR, const { ... } blocks get access to generic parameters (including const generic parameters?). Then maybe this:

fn foo<const N: usize>() {
    const M: usize = const { N };
}

would compile. But someone with deeper knowledge of constant evaluation in Rust is needed to give you a definitive answer.

1 Like

Thanks! I would look into inline_const to maybe find a workaround.

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.