Rollup merge of #117561 - tgross35:split-array, r=scottmcm
Stabilize `slice_first_last_chunk` This PR does a few different things based around stabilizing `slice_first_last_chunk`. They are split up so this PR can be by-commit reviewed, I can move parts to a separate PR if desired. This feature provides a very elegant API to extract arrays from either end of a slice, such as for parsing integers from binary data. ## Stabilize `slice_first_last_chunk` ACP: https://github.com/rust-lang/libs-team/issues/69 Implementation: https://github.com/rust-lang/rust/issues/90091 Tracking issue: https://github.com/rust-lang/rust/issues/111774 This stabilizes the functionality from https://github.com/rust-lang/rust/issues/111774: ```rust impl [T] { pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]>; pub fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]>; pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]>; pub fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]>; pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])>; pub fn split_first_chunk_mut<const N: usize>(&mut self) -> Option<(&mut [T; N], &mut [T])>; pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])>; pub fn split_last_chunk_mut<const N: usize>(&mut self) -> Option<(&mut [T], &mut [T; N])>; } ``` Const stabilization is included for all non-mut methods, which are blocked on `const_mut_refs`. This change includes marking the trivial function `slice_split_at_unchecked` const-stable for internal use (but not fully stable). ## Remove `split_array` slice methods Tracking issue: https://github.com/rust-lang/rust/issues/90091 Implementation: https://github.com/rust-lang/rust/pull/83233#pullrequestreview-780315524 This PR also removes the following unstable methods from the `split_array` feature, https://github.com/rust-lang/rust/issues/90091: ```rust impl<T> [T] { pub fn split_array_ref<const N: usize>(&self) -> (&[T; N], &[T]); pub fn split_array_mut<const N: usize>(&mut self) -> (&mut [T; N], &mut [T]); pub fn rsplit_array_ref<const N: usize>(&self) -> (&[T], &[T; N]); pub fn rsplit_array_mut<const N: usize>(&mut self) -> (&mut [T], &mut [T; N]); } ``` This is done because discussion at #90091 and its implementation PR indicate a strong preference for nonpanicking APIs that return `Option`. The only difference between functions under the `split_array` and `slice_first_last_chunk` features is `Option` vs. panic, so remove the duplicates as part of this stabilization. This does not affect the array methods from `split_array`. We will want to revisit these once `generic_const_exprs` is further along. ## Reverse order of return tuple for `split_last_chunk{,_mut}` An unresolved question for #111774 is whether to return `(preceding_slice, last_chunk)` (`(&[T], &[T; N])`) or the reverse (`(&[T; N], &[T])`), from `split_last_chunk` and `split_last_chunk_mut`. It is currently implemented as `(last_chunk, preceding_slice)` which matches `split_last -> (&T, &[T])`. The first commit changes these to `(&[T], &[T; N])` for these reasons: - More consistent with other splitting methods that return multiple values: `str::rsplit_once`, `slice::split_at{,_mut}`, `slice::align_to` all return tuples with the items in order - More intuitive (arguably opinion, but it is consistent with other language elements like pattern matching `let [a, b, rest @ ..] ...` - If we ever added a varidic way to obtain multiple chunks, it would likely return something in order: `.split_many_last::<(2, 4)>() -> (&[T], &[T; 2], &[T; 4])` - It is the ordering used in the `rsplit_array` methods I think the inconsistency with `split_last` could be acceptable in this case, since for `split_last` the scalar `&T` doesn't have any internal order to maintain with the other items. ## Unresolved questions Do we want to reserve the same names on `[u8; N]` to avoid inference confusion? https://github.com/rust-lang/rust/pull/117561#issuecomment-1793388647 --- `slice_first_last_chunk` has only been around since early 2023, but `split_array` has been around since 2021. `@rustbot` label -T-libs +T-libs-api -T-libs +needs-fcp cc `@rust-lang/wg-const-eval,` `@scottmcm` who raised this topic, `@clarfonthey` implementer of `slice_first_last_chunk` `@jethrogb` implementer of `split_array` Zulip discussion: https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Stabilizing.20array-from-slice.20*something*.3F Fixes: #111774
This commit is contained in:
commit
64461dab01
@ -16,7 +16,6 @@
|
|||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(ptr_sub_ptr)]
|
#![feature(ptr_sub_ptr)]
|
||||||
#![feature(slice_first_last_chunk)]
|
|
||||||
#![cfg_attr(test, feature(test))]
|
#![cfg_attr(test, feature(test))]
|
||||||
#![allow(rustc::internal)]
|
#![allow(rustc::internal)]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
|
@ -647,7 +647,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) {
|
pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) {
|
||||||
(&self[..]).split_array_ref::<M>()
|
(&self[..]).split_first_chunk::<M>().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Divides one mutable array reference into two at an index.
|
/// Divides one mutable array reference into two at an index.
|
||||||
@ -680,7 +680,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
|
pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
|
||||||
(&mut self[..]).split_array_mut::<M>()
|
(&mut self[..]).split_first_chunk_mut::<M>().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Divides one array reference into two at an index from the end.
|
/// Divides one array reference into two at an index from the end.
|
||||||
@ -725,7 +725,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
|
pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
|
||||||
(&self[..]).rsplit_array_ref::<M>()
|
(&self[..]).split_last_chunk::<M>().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Divides one mutable array reference into two at an index from the end.
|
/// Divides one mutable array reference into two at an index from the end.
|
||||||
@ -758,7 +758,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
|
pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
|
||||||
(&mut self[..]).rsplit_array_mut::<M>()
|
(&mut self[..]).split_last_chunk_mut::<M>().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ pub const fn last(&self) -> Option<&T> {
|
|||||||
if let [.., last] = self { Some(last) } else { None }
|
if let [.., last] = self { Some(last) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable pointer to the last item in the slice.
|
/// Returns a mutable reference to the last item in the slice.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -316,13 +316,13 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
|
|||||||
if let [.., last] = self { Some(last) } else { None }
|
if let [.., last] = self { Some(last) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the first `N` elements of the slice, or `None` if it has fewer than `N` elements.
|
/// Return an array reference to the first `N` items in the slice.
|
||||||
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let u = [10, 40, 30];
|
/// let u = [10, 40, 30];
|
||||||
/// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
|
/// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
|
||||||
///
|
///
|
||||||
@ -332,27 +332,26 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
|
|||||||
/// let w: &[i32] = &[];
|
/// let w: &[i32] = &[];
|
||||||
/// assert_eq!(Some(&[]), w.first_chunk::<0>());
|
/// assert_eq!(Some(&[]), w.first_chunk::<0>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]> {
|
pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]> {
|
||||||
if self.len() < N {
|
if self.len() < N {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// and do not let the reference outlive the slice.
|
// and do not let the reference outlive the slice.
|
||||||
Some(unsafe { &*(self.as_ptr() as *const [T; N]) })
|
Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable reference to the first `N` elements of the slice,
|
/// Return a mutable array reference to the first `N` items in the slice.
|
||||||
/// or `None` if it has fewer than `N` elements.
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let x = &mut [0, 1, 2];
|
/// let x = &mut [0, 1, 2];
|
||||||
///
|
///
|
||||||
/// if let Some(first) = x.first_chunk_mut::<2>() {
|
/// if let Some(first) = x.first_chunk_mut::<2>() {
|
||||||
@ -360,10 +359,12 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
|
|||||||
/// first[1] = 4;
|
/// first[1] = 4;
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(x, &[5, 4, 2]);
|
/// assert_eq!(x, &[5, 4, 2]);
|
||||||
|
///
|
||||||
|
/// assert_eq!(None, x.first_chunk_mut::<4>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")]
|
||||||
pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
|
pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
|
||||||
if self.len() < N {
|
if self.len() < N {
|
||||||
None
|
None
|
||||||
@ -371,28 +372,29 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
|
|||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// do not let the reference outlive the slice,
|
// do not let the reference outlive the slice,
|
||||||
// and require exclusive access to the entire slice to mutate the chunk.
|
// and require exclusive access to the entire slice to mutate the chunk.
|
||||||
Some(unsafe { &mut *(self.as_mut_ptr() as *mut [T; N]) })
|
Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the first `N` elements of the slice and the remainder,
|
/// Return an array reference to the first `N` items in the slice and the remaining slice.
|
||||||
/// or `None` if it has fewer than `N` elements.
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let x = &[0, 1, 2];
|
/// let x = &[0, 1, 2];
|
||||||
///
|
///
|
||||||
/// if let Some((first, elements)) = x.split_first_chunk::<2>() {
|
/// if let Some((first, elements)) = x.split_first_chunk::<2>() {
|
||||||
/// assert_eq!(first, &[0, 1]);
|
/// assert_eq!(first, &[0, 1]);
|
||||||
/// assert_eq!(elements, &[2]);
|
/// assert_eq!(elements, &[2]);
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(None, x.split_first_chunk::<4>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
|
pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
|
||||||
if self.len() < N {
|
if self.len() < N {
|
||||||
None
|
None
|
||||||
@ -402,18 +404,18 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
|
|||||||
|
|
||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// and do not let the references outlive the slice.
|
// and do not let the references outlive the slice.
|
||||||
Some((unsafe { &*(first.as_ptr() as *const [T; N]) }, tail))
|
Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable reference to the first `N` elements of the slice and the remainder,
|
/// Return a mutable array reference to the first `N` items in the slice and the remaining
|
||||||
/// or `None` if it has fewer than `N` elements.
|
/// slice.
|
||||||
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let x = &mut [0, 1, 2];
|
/// let x = &mut [0, 1, 2];
|
||||||
///
|
///
|
||||||
/// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
|
/// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
|
||||||
@ -422,10 +424,12 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
|
|||||||
/// elements[0] = 5;
|
/// elements[0] = 5;
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(x, &[3, 4, 5]);
|
/// assert_eq!(x, &[3, 4, 5]);
|
||||||
|
///
|
||||||
|
/// assert_eq!(None, x.split_first_chunk_mut::<4>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")]
|
||||||
pub const fn split_first_chunk_mut<const N: usize>(
|
pub const fn split_first_chunk_mut<const N: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Option<(&mut [T; N], &mut [T])> {
|
) -> Option<(&mut [T; N], &mut [T])> {
|
||||||
@ -438,29 +442,30 @@ pub const fn split_first_chunk_mut<const N: usize>(
|
|||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// do not let the reference outlive the slice,
|
// do not let the reference outlive the slice,
|
||||||
// and enforce exclusive mutability of the chunk by the split.
|
// and enforce exclusive mutability of the chunk by the split.
|
||||||
Some((unsafe { &mut *(first.as_mut_ptr() as *mut [T; N]) }, tail))
|
Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last `N` elements of the slice and the remainder,
|
/// Return an array reference to the last `N` items in the slice and the remaining slice.
|
||||||
/// or `None` if it has fewer than `N` elements.
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let x = &[0, 1, 2];
|
/// let x = &[0, 1, 2];
|
||||||
///
|
///
|
||||||
/// if let Some((last, elements)) = x.split_last_chunk::<2>() {
|
/// if let Some((elements, last)) = x.split_last_chunk::<2>() {
|
||||||
/// assert_eq!(last, &[1, 2]);
|
|
||||||
/// assert_eq!(elements, &[0]);
|
/// assert_eq!(elements, &[0]);
|
||||||
|
/// assert_eq!(last, &[1, 2]);
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(None, x.split_last_chunk::<4>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])> {
|
||||||
if self.len() < N {
|
if self.len() < N {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -469,32 +474,35 @@ pub const fn split_first_chunk_mut<const N: usize>(
|
|||||||
|
|
||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// and do not let the references outlive the slice.
|
// and do not let the references outlive the slice.
|
||||||
Some((unsafe { &*(last.as_ptr() as *const [T; N]) }, init))
|
Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
|
/// Return a mutable array reference to the last `N` items in the slice and the remaining
|
||||||
|
/// slice.
|
||||||
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let x = &mut [0, 1, 2];
|
/// let x = &mut [0, 1, 2];
|
||||||
///
|
///
|
||||||
/// if let Some((last, elements)) = x.split_last_chunk_mut::<2>() {
|
/// if let Some((elements, last)) = x.split_last_chunk_mut::<2>() {
|
||||||
/// last[0] = 3;
|
/// last[0] = 3;
|
||||||
/// last[1] = 4;
|
/// last[1] = 4;
|
||||||
/// elements[0] = 5;
|
/// elements[0] = 5;
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(x, &[5, 3, 4]);
|
/// assert_eq!(x, &[5, 3, 4]);
|
||||||
|
///
|
||||||
|
/// assert_eq!(None, x.split_last_chunk_mut::<4>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")]
|
||||||
pub const fn split_last_chunk_mut<const N: usize>(
|
pub const fn split_last_chunk_mut<const N: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Option<(&mut [T; N], &mut [T])> {
|
) -> Option<(&mut [T], &mut [T; N])> {
|
||||||
if self.len() < N {
|
if self.len() < N {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -504,17 +512,17 @@ pub const fn split_last_chunk_mut<const N: usize>(
|
|||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// do not let the reference outlive the slice,
|
// do not let the reference outlive the slice,
|
||||||
// and enforce exclusive mutability of the chunk by the split.
|
// and enforce exclusive mutability of the chunk by the split.
|
||||||
Some((unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }, init))
|
Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last element of the slice, or `None` if it is empty.
|
/// Return an array reference to the last `N` items in the slice.
|
||||||
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let u = [10, 40, 30];
|
/// let u = [10, 40, 30];
|
||||||
/// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
|
/// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
|
||||||
///
|
///
|
||||||
@ -524,9 +532,9 @@ pub const fn split_last_chunk_mut<const N: usize>(
|
|||||||
/// let w: &[i32] = &[];
|
/// let w: &[i32] = &[];
|
||||||
/// assert_eq!(Some(&[]), w.last_chunk::<0>());
|
/// assert_eq!(Some(&[]), w.last_chunk::<0>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")]
|
||||||
pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
|
pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
|
||||||
if self.len() < N {
|
if self.len() < N {
|
||||||
None
|
None
|
||||||
@ -537,17 +545,17 @@ pub const fn split_last_chunk_mut<const N: usize>(
|
|||||||
|
|
||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// and do not let the references outlive the slice.
|
// and do not let the references outlive the slice.
|
||||||
Some(unsafe { &*(last.as_ptr() as *const [T; N]) })
|
Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable pointer to the last item in the slice.
|
/// Return a mutable array reference to the last `N` items in the slice.
|
||||||
|
///
|
||||||
|
/// If the slice is not at least `N` in length, this will return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_first_last_chunk)]
|
|
||||||
///
|
|
||||||
/// let x = &mut [0, 1, 2];
|
/// let x = &mut [0, 1, 2];
|
||||||
///
|
///
|
||||||
/// if let Some(last) = x.last_chunk_mut::<2>() {
|
/// if let Some(last) = x.last_chunk_mut::<2>() {
|
||||||
@ -555,10 +563,12 @@ pub const fn split_last_chunk_mut<const N: usize>(
|
|||||||
/// last[1] = 20;
|
/// last[1] = 20;
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(x, &[0, 10, 20]);
|
/// assert_eq!(x, &[0, 10, 20]);
|
||||||
|
///
|
||||||
|
/// assert_eq!(None, x.last_chunk_mut::<4>());
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")]
|
||||||
pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
|
pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
|
||||||
if self.len() < N {
|
if self.len() < N {
|
||||||
None
|
None
|
||||||
@ -570,7 +580,7 @@ pub const fn split_last_chunk_mut<const N: usize>(
|
|||||||
// SAFETY: We explicitly check for the correct number of elements,
|
// SAFETY: We explicitly check for the correct number of elements,
|
||||||
// do not let the reference outlive the slice,
|
// do not let the reference outlive the slice,
|
||||||
// and require exclusive access to the entire slice to mutate the chunk.
|
// and require exclusive access to the entire slice to mutate the chunk.
|
||||||
Some(unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) })
|
Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1859,7 +1869,6 @@ pub fn group_by_mut<F>(&mut self, pred: F) -> GroupByMut<'_, T, F>
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")]
|
#[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")]
|
||||||
#[rustc_allow_const_fn_unstable(slice_split_at_unchecked)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -1946,7 +1955,10 @@ pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")]
|
#[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")]
|
||||||
#[rustc_const_unstable(feature = "slice_split_at_unchecked", issue = "76014")]
|
#[rustc_const_stable(
|
||||||
|
feature = "const_slice_split_at_unchecked",
|
||||||
|
since = "CURRENT_RUSTC_VERSION"
|
||||||
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) {
|
pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) {
|
||||||
@ -2019,164 +2031,6 @@ pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
|
|||||||
unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
|
unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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]
|
|
||||||
#[track_caller]
|
|
||||||
#[must_use]
|
|
||||||
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]
|
|
||||||
#[track_caller]
|
|
||||||
#[must_use]
|
|
||||||
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) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Divides one slice into an array and a remainder slice at an index from
|
|
||||||
/// the end.
|
|
||||||
///
|
|
||||||
/// The slice will contain all indices from `[0, len - N)` (excluding
|
|
||||||
/// the index `len - N` itself) and the array will contain all
|
|
||||||
/// indices from `[len - 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.rsplit_array_ref::<0>();
|
|
||||||
/// assert_eq!(left, [1, 2, 3, 4, 5, 6]);
|
|
||||||
/// assert_eq!(right, &[]);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// {
|
|
||||||
/// let (left, right) = v.rsplit_array_ref::<2>();
|
|
||||||
/// assert_eq!(left, [1, 2, 3, 4]);
|
|
||||||
/// assert_eq!(right, &[5, 6]);
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// {
|
|
||||||
/// let (left, right) = v.rsplit_array_ref::<6>();
|
|
||||||
/// assert_eq!(left, []);
|
|
||||||
/// assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[unstable(feature = "split_array", reason = "new API", issue = "90091")]
|
|
||||||
#[inline]
|
|
||||||
#[must_use]
|
|
||||||
pub fn rsplit_array_ref<const N: usize>(&self) -> (&[T], &[T; N]) {
|
|
||||||
assert!(N <= self.len());
|
|
||||||
let (a, b) = self.split_at(self.len() - N);
|
|
||||||
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at)
|
|
||||||
unsafe { (a, &*(b.as_ptr() as *const [T; N])) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Divides one mutable slice into an array and a remainder slice at an
|
|
||||||
/// index from the end.
|
|
||||||
///
|
|
||||||
/// The slice will contain all indices from `[0, len - N)` (excluding
|
|
||||||
/// the index `N` itself) and the array will contain all
|
|
||||||
/// indices from `[len - 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.rsplit_array_mut::<4>();
|
|
||||||
/// assert_eq!(left, [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 = "new API", issue = "90091")]
|
|
||||||
#[inline]
|
|
||||||
#[must_use]
|
|
||||||
pub fn rsplit_array_mut<const N: usize>(&mut self) -> (&mut [T], &mut [T; N]) {
|
|
||||||
assert!(N <= self.len());
|
|
||||||
let (a, b) = self.split_at_mut(self.len() - N);
|
|
||||||
// SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
|
|
||||||
unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator over subslices separated by elements that match
|
/// Returns an iterator over subslices separated by elements that match
|
||||||
/// `pred`. The matched element is not contained in the subslices.
|
/// `pred`. The matched element is not contained in the subslices.
|
||||||
///
|
///
|
||||||
|
@ -2398,37 +2398,45 @@ fn index_b_greater_than_len() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slice_split_array_mut() {
|
fn slice_split_first_chunk_mut() {
|
||||||
let v = &mut [1, 2, 3, 4, 5, 6][..];
|
let v = &mut [1, 2, 3, 4, 5, 6][..];
|
||||||
|
|
||||||
{
|
{
|
||||||
let (left, right) = v.split_array_mut::<0>();
|
let (left, right) = v.split_first_chunk_mut::<0>().unwrap();
|
||||||
assert_eq!(left, &mut []);
|
assert_eq!(left, &mut []);
|
||||||
assert_eq!(right, [1, 2, 3, 4, 5, 6]);
|
assert_eq!(right, [1, 2, 3, 4, 5, 6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let (left, right) = v.split_array_mut::<6>();
|
let (left, right) = v.split_first_chunk_mut::<6>().unwrap();
|
||||||
assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]);
|
assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]);
|
||||||
assert_eq!(right, []);
|
assert_eq!(right, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
assert!(v.split_first_chunk_mut::<7>().is_none());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slice_rsplit_array_mut() {
|
fn slice_split_last_chunk_mut() {
|
||||||
let v = &mut [1, 2, 3, 4, 5, 6][..];
|
let v = &mut [1, 2, 3, 4, 5, 6][..];
|
||||||
|
|
||||||
{
|
{
|
||||||
let (left, right) = v.rsplit_array_mut::<0>();
|
let (left, right) = v.split_last_chunk_mut::<0>().unwrap();
|
||||||
assert_eq!(left, [1, 2, 3, 4, 5, 6]);
|
assert_eq!(left, [1, 2, 3, 4, 5, 6]);
|
||||||
assert_eq!(right, &mut []);
|
assert_eq!(right, &mut []);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let (left, right) = v.rsplit_array_mut::<6>();
|
let (left, right) = v.split_last_chunk_mut::<6>().unwrap();
|
||||||
assert_eq!(left, []);
|
assert_eq!(left, []);
|
||||||
assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
|
assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
assert!(v.split_last_chunk_mut::<7>().is_none());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2443,38 +2451,6 @@ fn split_as_slice() {
|
|||||||
assert_eq!(split.as_slice(), &[]);
|
assert_eq!(split.as_slice(), &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[should_panic]
|
|
||||||
#[test]
|
|
||||||
fn slice_split_array_ref_out_of_bounds() {
|
|
||||||
let v = &[1, 2, 3, 4, 5, 6][..];
|
|
||||||
|
|
||||||
let _ = 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][..];
|
|
||||||
|
|
||||||
let _ = v.split_array_mut::<7>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[should_panic]
|
|
||||||
#[test]
|
|
||||||
fn slice_rsplit_array_ref_out_of_bounds() {
|
|
||||||
let v = &[1, 2, 3, 4, 5, 6][..];
|
|
||||||
|
|
||||||
let _ = v.rsplit_array_ref::<7>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[should_panic]
|
|
||||||
#[test]
|
|
||||||
fn slice_rsplit_array_mut_out_of_bounds() {
|
|
||||||
let v = &mut [1, 2, 3, 4, 5, 6][..];
|
|
||||||
|
|
||||||
let _ = v.rsplit_array_mut::<7>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slice_split_once() {
|
fn slice_split_once() {
|
||||||
let v = &[1, 2, 3, 2, 4][..];
|
let v = &[1, 2, 3, 2, 4][..];
|
||||||
|
Loading…
Reference in New Issue
Block a user