Skip to content

Commit 274a7e0

Browse files
committed
Return two arrays from split_array_* methods on arrays
This also turns post-mono errors due to invalid indices into type errors.
1 parent 27e681f commit 274a7e0

File tree

2 files changed

+37
-36
lines changed

2 files changed

+37
-36
lines changed

library/core/src/array/mod.rs

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -656,16 +656,16 @@ impl<T, const N: usize> [T; N] {
656656
/// assert_eq!(right, &[]);
657657
/// }
658658
/// ```
659-
#[unstable(
660-
feature = "split_array",
661-
reason = "return type should have array as 2nd element",
662-
issue = "90091"
663-
)]
659+
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
664660
#[inline]
665-
pub const fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) {
666-
// FIXME: remove once constraint is encoded in return type
667-
const { assert!(M <= N) }
668-
self.as_slice().split_array_ref::<M>().unwrap()
661+
pub const fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T; N - M]) {
662+
// SAFETY: 0 <= M <= len (N)
663+
let (left, right) = unsafe { self.split_at_unchecked(M) };
664+
665+
// SAFETY: `split_at_unchecked()` guarantees that:
666+
// - `left` is a slice of `M` elements,
667+
// - `right` is a slice of `N - M` elements.
668+
unsafe { (from_slice_unchecked(left), from_slice_unchecked(right)) }
669669
}
670670

671671
/// Divides one mutable array reference into two at an index.
@@ -687,16 +687,16 @@ impl<T, const N: usize> [T; N] {
687687
/// right[1] = 4;
688688
/// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
689689
/// ```
690-
#[unstable(
691-
feature = "split_array",
692-
reason = "return type should have array as 2nd element",
693-
issue = "90091"
694-
)]
690+
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
695691
#[inline]
696-
pub const fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
697-
// FIXME: remove once constraint is encoded in return type
698-
const { assert!(M <= N) }
699-
(self as &mut [T]).split_array_mut::<M>().unwrap()
692+
pub const fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T; N - M]) {
693+
// SAFETY: 0 <= M <= len (N)
694+
let (left, right) = unsafe { self.split_at_mut_unchecked(M) };
695+
696+
// SAFETY: `split_at_mut_unchecked()` guarantees that:
697+
// - `left` is a slice of `M` elements,
698+
// - `right` is a slice of `N - M` elements.
699+
unsafe { (from_mut_slice_unchecked(left), from_mut_slice_unchecked(right)) }
700700
}
701701

702702
/// Divides one array reference into two at an index from the end.
@@ -730,16 +730,16 @@ impl<T, const N: usize> [T; N] {
730730
/// assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
731731
/// }
732732
/// ```
733-
#[unstable(
734-
feature = "split_array",
735-
reason = "return type should have array as 2nd element",
736-
issue = "90091"
737-
)]
733+
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
738734
#[inline]
739-
pub const fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
740-
// FIXME: remove once constraint is encoded in return type
741-
const { assert!(M <= N) }
742-
self.as_slice().rsplit_array_ref::<M>().unwrap()
735+
pub const fn rsplit_array_ref<const M: usize>(&self) -> (&[T; N - M], &[T; M]) {
736+
// SAFETY: 0 <= (N-M) <= len (N)
737+
let (left, right) = unsafe { self.split_at_unchecked(N - M) };
738+
739+
// SAFETY: `split_at_unchecked()` guarantees that:
740+
// - `left` is a slice of `N-M` elements,
741+
// - `right` is a slice of `N - (N-M) == M` elements.
742+
unsafe { (from_slice_unchecked(left), from_slice_unchecked(right)) }
743743
}
744744

745745
/// Divides one mutable array reference into two at an index from the end.
@@ -761,16 +761,16 @@ impl<T, const N: usize> [T; N] {
761761
/// right[1] = 4;
762762
/// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
763763
/// ```
764-
#[unstable(
765-
feature = "split_array",
766-
reason = "return type should have array as 2nd element",
767-
issue = "90091"
768-
)]
764+
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
769765
#[inline]
770-
pub const fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
771-
// FIXME: remove once constraint is encoded in return type
772-
const { assert!(M <= N) }
773-
(self as &mut [T]).rsplit_array_mut::<M>().unwrap()
766+
pub const fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T; N - M], &mut [T; M]) {
767+
// SAFETY: 0 <= (N-M) <= len (N)
768+
let (left, right) = unsafe { self.split_at_mut_unchecked(N - M) };
769+
770+
// SAFETY: `split_at_mut_unchecked()` guarantees that:
771+
// - `left` is a slice of `N-M` elements,
772+
// - `right` is a slice of `N - (N-M) == M` elements.
773+
unsafe { (from_mut_slice_unchecked(left), from_mut_slice_unchecked(right)) }
774774
}
775775
}
776776

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
#![feature(const_waker)]
165165
#![feature(core_panic)]
166166
#![feature(duration_consts_float)]
167+
#![feature(generic_const_exprs)]
167168
#![feature(internal_impls_macro)]
168169
#![feature(ip)]
169170
#![feature(is_ascii_octdigit)]

0 commit comments

Comments
 (0)