#unconstrained generic constant for const split array mut

17 messages · Page 1 of 1 (latest)

sudden charm
#

I trying to write a generic function called generic_concat which concatenates two arrays.
The implementation works without generics, but with generics, I get error: unconstrained generic constant

(Commented code does not work and causes the error)

#![allow(incomplete_features)]
#![feature(const_trait_impl)]
#![feature(generic_const_exprs)]
#![feature(const_mut_refs)]

use std::ptr;

#[inline(always)]
const unsafe fn ptr_slice_to_array_mut<'a, T, const N: usize>(slice: *mut [T]) -> &'a mut [T; N] {
    &mut *(slice as *mut [T; N])
}

pub trait ArrayHelper<T, const N: usize> {
    fn const_split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T; N - M]);
}

impl<T, const N: usize> const ArrayHelper<T, N> for [T; N]
{
    #[inline]
    fn const_split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T; N - M]) {
        assert!(M <= N, "Bounds check failure in `[T; N]::split_array_mut'!");
        let self_ptr = self.as_mut_ptr();
        unsafe {
            let left = ptr::slice_from_raw_parts_mut(self_ptr, M);
            let right = ptr::slice_from_raw_parts_mut(self_ptr.add(M), N - M);
            (ptr_slice_to_array_mut(left), ptr_slice_to_array_mut(right))
        }
    }
}


fn concat(a: &[u16; 128], b: &[u16; 128]) -> [u16; 256] {
    let mut whole: [u16; 256] = [Default::default(); 256];
    let (one, two) = whole.const_split_array_mut::<128>();
    one.copy_from_slice(a);
    two.copy_from_slice(b);
    whole
}

pub fn it_works(a: [u16; 128], b: [u16; 128]) -> [u16; 256] {
    concat(&a,&b)
}


// fn generic_concat<T: Copy + Default, const M: usize, const N: usize>(a: &[T; M], b: &[T; N]) -> [T; M+N] {
//     let mut whole: [T; M+N] = [Default::default(); M+N];
//     let (one, two) = whole.const_split_array_mut::<M>();
//     one.copy_from_slice(a);
//     two.copy_from_slice(b);
//     whole
// }

// pub fn it_does_not_works(a: [u16; 128], b: [u16; 128]) -> [u16; 256] {
//     generic_concat(&a,&b)
// }
sly rose
#

(you can keep the M/N names instead and write where [(); M+N-M], just then it's less clear that the fix recommendations the compiler gives are bugged out)

sudden charm
#

Why is X+Y-X needed?

sly rose
#

because the generic consts stuff doesn't do math really

#

so it can't see that X+Y-X is guaranteed to not overflow (because you have X+Y written as a requirement) or underflow (because if it doesn't overflow, it's just Y)

sudden charm
#

Oh I see, as generic const is incomplete, will it be able to do math in the future?

sly rose
#

I don't know the plans there

sudden charm
#

No worries, thank you for the help!
I do wish the compiler error was a bit more helpful!

sly rose
#

(doing good symbolic computation is not exactly trivial)

#

yeah, the fix recommendation there is flat up wrong

sudden charm
sly rose
#

in at least some versions it's pointing to generic_concat but using names from const_split_array_mut

#

it should instead use the substituted values that are correct for generic_concat

sudden charm
#

e.g. they should have replaced the N here N - M with M+N to give M+N-M

sly rose
#

yeah

#

(and replaced the M with the logically different M :P)