Change:
Creating a new issue about const-generic array splitting methods since it's been discussed on the , where it really doesn't belong. We probably want The possibility of a variadic array splitting function was also mentioned (at least that's my interpretation) but since there's not even an active RFC about variadic generics, I think that's a bit out of scope. The only thing one could do once the second above becomes possible is add , and so on.
We also need two or more different use cases.
pointed out that this could be implemented today by taking 2 const params, but the check that they subdivide the array evenly would have to be a runtime assertion. ` We could add the API on nightly with an awareness that we intend to change the API someday.
I made an implementation that errors at compiletime when you specify wrong array lengths! Here a playground link for a PoC:
use case: Parsing binary data into structs that contain fixed-length arrays
I think something that uses traits to impose relational const constraints makes more sense outside of std right now.
yeah, the error message you get when the assert hits is far from pretty and usefull. I'd say its a tradeoff between wanting some ugly compile error whenever the lenghts are wrong, or taking that assertion and finding out the lenghts are wrong during runtime. One thing to make the error a little bit nicer, is to write the following: Now, if somehow the values of , and could be displayed in that message, it would be even nicer
Compile-time errors are better. This means we need to add something to Rust to perform similar static casts in a nicer and shorter way.
Aren't you the same leonardo from the internals forum who created about this exact feature a week ago? I responded there with an explanation of the state of things in regard to that feature. In any event the "correct" API is not to have two parameters and constrain them, but to derive the length of the second array by subtracting the a single parameter from the length of the main array. (). But the current implementation of const generics does not support that. Probably it would be better to hash out what APIs we could implement now, and whether its worth adding them to nightly, in a zulip thread than a GitHub issue.
There I asked for a "where" clause on const integers, while here I've suggested about a more general const_assert that's usable in more/different cases.
Here is an example implementation: (EDIT: Updated features) ()
Is it possible to add now but adjust the signature so that its use is always a compile-time error? I'd like to land the slice version ASAP but I don't want to run into the same problem we had with .
Another use case: converting binary data to integers using
This seems easy: just keep the array version unstable?
This is 100% doable in current nightly rust, in a way that simply results in an immediate compile-time error if an invalid split index is provided, and is also completely -compatible. as a impl of the following trait (which is just a stand-in for the actual type, of course):
To split an array or slice with this functions I'm using: let (a1, rest) = data.splitarrayref::<N(); let (a2, empty) = rest.splitarrayref::<M(); assert!(empty.isempty()); (a1, a2) I guess there isn't a desire for a array method similar to: fn splitintotwoarrays<T, const N: usize, const M: usize(data: &[T; N]) -(&[T; M], &[T; N - M]) {
I think I'd use splitarrayref followed by try_from on the rest.
Check the tracking issue for more details on exact-length splitting for arrays.

Discussion:
// items. unsafe { collect_into_array_unchecked(&mut self.iter_mut()) } } <ins> /// Divides one array reference into two at an index. /// /// The first will contain all indices from `[0, M)` (excluding /// the index `M` itself) and the second will contain all /// indices from `[M, N)` (excluding the index `N` itself). /// /// # Panics /// /// Panics if `M > N`. /// /// # Examples /// /// ``` /// #![feature(split_array)] /// /// let v = [1, 2, 3, 4, 5, 6]; /// /// { ///    let (left, right) = v.split_array_ref::<0>(); ///    assert_eq!(left, &[]); ///    assert_eq!(right, &[1, 2, 3, 4, 5, 6]); /// } /// /// { ///     let (left, right) = v.split_array_ref::<2>(); ///     assert_eq!(left, &[1, 2]); ///     assert_eq!(right, &[3, 4, 5, 6]); /// } /// /// { ///     let (left, right) = v.split_array_ref::<6>(); ///     assert_eq!(left, &[1, 2, 3, 4, 5, 6]); ///     assert_eq!(right, &[]); /// } /// ``` #[unstable( feature = "split_array", reason = "return type should have array as 2nd element", issue = "90091" )] #[inline] pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) { (&self[..]).split_array_ref::<M>() } /// Divides one mutable array reference into two at an index. /// /// The first will contain all indices from `[0, M)` (excluding /// the index `M` itself) and the second will contain all /// indices from `[M, N)` (excluding the index `N` itself). /// /// # Panics /// /// Panics if `M > N`. /// /// # Examples /// /// ``` /// #![feature(split_array)] /// /// let mut v = [1, 0, 3, 0, 5, 6]; /// let (left, right) = v.split_array_mut::<2>(); /// assert_eq!(left, &mut [1, 0][..]); /// assert_eq!(right, &mut [3, 0, 5, 6]); /// left[1] = 2; /// right[1] = 4; /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[unstable( feature = "split_array", reason = "return type should have array as 2nd element", issue = "90091" )] #[inline] pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) { (&mut self[..]).split_array_mut::<M>() } </ins> } /// Pulls `N` items from `iter` and returns them as an array. If the iterator

unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } } <ins> /// Divides one slice into an array and a remainder slice at an index. /// /// The array will contain all indices from `[0, N)` (excluding /// the index `N` itself) and the slice will contain all /// indices from `[N, len)` (excluding the index `len` itself). /// /// # Panics /// /// Panics if `N > len`. /// /// # Examples /// /// ``` /// #![feature(split_array)] /// /// let v = &[1, 2, 3, 4, 5, 6][..]; /// /// { ///    let (left, right) = v.split_array_ref::<0>(); ///    assert_eq!(left, &[]); ///    assert_eq!(right, [1, 2, 3, 4, 5, 6]); /// } /// /// { ///     let (left, right) = v.split_array_ref::<2>(); ///     assert_eq!(left, &[1, 2]); ///     assert_eq!(right, [3, 4, 5, 6]); /// } /// /// { ///     let (left, right) = v.split_array_ref::<6>(); ///     assert_eq!(left, &[1, 2, 3, 4, 5, 6]); ///     assert_eq!(right, []); /// } /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] pub fn split_array_ref<const N: usize>(&self) -> (&[T; N], &[T]) { let (a, b) = self.split_at(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at) unsafe { (&*(a.as_ptr() as *const [T; N]), b) } } /// Divides one mutable slice into an array and a remainder slice at an index. /// /// The array will contain all indices from `[0, N)` (excluding /// the index `N` itself) and the slice will contain all /// indices from `[N, len)` (excluding the index `len` itself). /// /// # Panics /// /// Panics if `N > len`. /// /// # Examples /// /// ``` /// #![feature(split_array)] /// /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; /// let (left, right) = v.split_array_mut::<2>(); /// assert_eq!(left, &mut [1, 0]); /// assert_eq!(right, [3, 0, 5, 6]); /// left[1] = 2; /// right[1] = 4; /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] pub fn split_array_mut<const N: usize>(&mut self) -> (&mut [T; N], &mut [T]) { let (a, b) = self.split_at_mut(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) } } </ins> /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. ///

std::panic::set_hook(prev_hook); result } <ins> #[test] fn array_split_array_mut() { let mut v = [1, 2, 3, 4, 5, 6]; { let (left, right) = v.split_array_mut::<0>(); assert_eq!(left, &mut []); assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); } { let (left, right) = v.split_array_mut::<6>(); assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); assert_eq!(right, &mut []); } } #[should_panic] #[test] fn array_split_array_ref_out_of_bounds() { let v = [1, 2, 3, 4, 5, 6]; v.split_array_ref::<7>(); } #[should_panic] #[test] fn array_split_array_mut_out_of_bounds() { let mut v = [1, 2, 3, 4, 5, 6]; v.split_array_mut::<7>(); } </ins>

#![feature(integer_atomics)] #![feature(int_roundings)] #![feature(slice_group_by)] <ins> #![feature(split_array)] </ins> #![feature(trusted_random_access)] #![feature(unsize)] #![feature(unzip_option)]

x.swap(2, 5); } } <ins> #[test] fn slice_split_array_mut() { let v = &mut [1, 2, 3, 4, 5, 6][..]; { let (left, right) = v.split_array_mut::<0>(); assert_eq!(left, &mut []); assert_eq!(right, [1, 2, 3, 4, 5, 6]); } { let (left, right) = v.split_array_mut::<6>(); assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); assert_eq!(right, []); } } #[should_panic] #[test] fn slice_split_array_ref_out_of_bounds() { let v = &[1, 2, 3, 4, 5, 6][..]; v.split_array_ref::<7>(); } #[should_panic] #[test] fn slice_split_array_mut_out_of_bounds() { let v = &mut [1, 2, 3, 4, 5, 6][..]; v.split_array_mut::<7>(); } </ins>