Associated const in traits with const generics

For some reason, think this what is happening, but not understanding totally. buff has array length with generic parameter, right?

no it doesn't work either

should without C

And now your not using a associated const from a trait in a generic context (which is currently not implemented or allowed). :slight_smile:

That issue is just for arrays, though, right?

No, it's an issue with all const generic parameters, arrays used to be special cased as the only types with const generic paramters so that's why the tracking issue just says array lengths. (Note: this special casing made them near useless in a generic context, which is why const-generics is such a useful feature, but also why it's so much work to implement)

What makes buff different from an array with a const generic parameter?

Nothing, it is an array with a const generic parameter. (I think I might not be explaining something properly, am I misunderstanding what you are trying to ask?)

Do not think so, think probably I am the one not explaining properly. Thanks for the patience. In other words, if array lengths do not support const generic parameters, why does buff work when it is an array that has length that is const generic?

For all arrays [T; N], N is that array's const generic parameter, in the same way that T is it's type parameter. So all arrays have const generic parameters.

I'm assuming your talking about this.

impl<const N: usize> T<N> for F<N> {
    fn f(v: &SliceVec<usize, N>) {
        let mut V = SliceVec {
            len: 10,
            buff: [MaybeUninit::new(0); 10],
        };
     }
 }

That's what const-generics was designed to do, allow you to generalize over all arrays. But work isn't complete, so associated consts don't work just yet.

I forgot to add, in this case you are initializing SliceVec with a literal 10, so V's type is inferred to be SliceVec<i32, 10>, (it doesn't depend on N, altough it could with min_const_generics)

I'm assuming your talking about this

No, referring to definition:

pub struct SliceVec<T, const N: usize> {
    pub len: usize,
    pub buff: [MaybeUninit<T>; N],
}

Why does SliceVec work? Why can rustc not make type inference? Probably worth adding that type annotations needed occurs before cannot infer the value of const parameter N declared on the trait Trait

it seems to work just find playground

impl<const N: usize> T<N> for F<N> {
    fn f(v: &SliceVec<usize, N>) {
        F::f(&SliceVec {
            len: 10,
            buff: [MaybeUninit::new(0); 10],
        });
    }
}

Even if you replace the array length 10 with N playground

impl<const N: usize> T<N> for F<N> {
    fn f(v: &SliceVec<usize, N>) {
        F::f(&SliceVec {
            len: 10,
            buff: [MaybeUninit::new(0); N],
        });
    }
}

Apologies for delay exceeded comment limit.

Second block does work, but it changes the function, since len and N are not necessarily the same. The question (this is the overlap with the original post) is why does adding multiplying C0

impl<const N: usize> T<N> for F<N> {
    fn f(v: &SliceVec<usize, N>) {
        const C: usize = C0*N;
        F::f(&SliceVec {
            len: C,
            buff: [MaybeUninit::new(0); C],
        });
    }
}

can't use generic parameters from outer function

This is a general limitation of all global items in Rust (static, global const, functions, and type definitions). You can't use type parameter from the enclosing scope.

However, this works: (no it doesn't)

impl<const N: usize> T<N> for F<N> {
    fn f(v: &SliceVec<usize, N>) {
        F::f(&SliceVec {
            len: C0*N,
            buff: [MaybeUninit::new(0); C0*N],
        });
    }
}

Would you mind explaining what is happening with F::f? This does seem to work in some way, but SliceVec returns () so assignment V = SliceVec and methods like max_len do not work. Is there a way to use this same sort of ::f call while preserving assignment, methods of SliceVec?

Separately, C0 global is not necessary in question design. Seems weird, since many trait impl should be able to use this global, but having many C0 local to f should work as long as all C0 are const. The reason is since using N in type assignment still yields cannot perform const operation using N, generic parameters may not be used in const operations, or use of generic parameter from outer function, even when C0 not global

I just verified my last answer, and it doesn't work. Sorry, my bad. For now, it looks like you can only directly name const-generic parameters, and have expressions that don't depend on const-generic parameters.

Operations on const-generic parameters haven't been implemented just yet. It looks like any way of trying to do this results in an error. (operations include the arithmetic operators, functions, anything beyond just naming they const generic parameter).

(As seen your the linked issue).

I've never seen that error before, but it looks like this is because operations not being allowed on const generic parameters. (looks like you don't need floating point to see the error playground).

(As seen your the linked issue).

Yes, but various comments are able to get this sort of thing to work in ways the are not yet displayed in here or in original post. As an example,

fn split_first<T, const N: usize>(arr: [T; N]) -> (T, [T; N - 1]) {
    let arr = mem::ManuallyDrop::new(arr);
    unsafe {
        let head = ptr::read(&arr[0]);
        let tail = ptr::read(&arr[1..] as *const [T] as *const [T; N - 1]);
        (head, tail)
    }
}

though the test() example unconstrained generic constant and asking for where clauses?

yet

So back to above, what is the best way to follow this? Searching by Github issue labels not particularly helpful and though some of the recent links are somewhat helpful (operations on const generic parameters are permitted in certain examples), but still not clear about how to use upstream const generic parameters operations. Is this the type of feature where needing knowledge of rustc to follow discussions?

Thankful for all your attentive responses, but if there is a place that may be better to ask this question, open to go there.

edit: To clarity, still unclear if using the approach from the linked issue is appropriate in the the original example. This is where relevant unconstrained generic constant This may work.
Thanks again for your help @RustyYato. New thread for cycle detected when building an abstract representation.

1 Like

I'm not sure where to look beyond the links I posted above

I completely forgot that this was possible. I'm not quite sure what to make of it.

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.