Skip to content

Make slice iterator constructors unstably const #137738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 25 additions & 20 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ unsafe impl<T: Sync> Send for Iter<'_, T> {}

impl<'a, T> Iter<'a, T> {
#[inline]
pub(super) fn new(slice: &'a [T]) -> Self {
pub(super) const fn new(slice: &'a [T]) -> Self {
let len = slice.len();
let ptr: NonNull<T> = NonNull::from(slice).cast();
let ptr: NonNull<T> = NonNull::from_ref(slice).cast();
// SAFETY: Similar to `IterMut::new`.
unsafe {
let end_or_len =
Expand Down Expand Up @@ -218,9 +218,9 @@ unsafe impl<T: Send> Send for IterMut<'_, T> {}

impl<'a, T> IterMut<'a, T> {
#[inline]
pub(super) fn new(slice: &'a mut [T]) -> Self {
pub(super) const fn new(slice: &'a mut [T]) -> Self {
let len = slice.len();
let ptr: NonNull<T> = NonNull::from(slice).cast();
let ptr: NonNull<T> = NonNull::from_mut(slice).cast();
// SAFETY: There are several things here:
//
// `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid
Expand Down Expand Up @@ -1335,7 +1335,7 @@ pub struct Windows<'a, T: 'a> {

impl<'a, T: 'a> Windows<'a, T> {
#[inline]
pub(super) fn new(slice: &'a [T], size: NonZero<usize>) -> Self {
pub(super) const fn new(slice: &'a [T], size: NonZero<usize>) -> Self {
Self { v: slice, size }
}
}
Expand Down Expand Up @@ -1487,7 +1487,7 @@ pub struct Chunks<'a, T: 'a> {

impl<'a, T: 'a> Chunks<'a, T> {
#[inline]
pub(super) fn new(slice: &'a [T], size: usize) -> Self {
pub(super) const fn new(slice: &'a [T], size: usize) -> Self {
Self { v: slice, chunk_size: size }
}
}
Expand Down Expand Up @@ -1677,7 +1677,7 @@ pub struct ChunksMut<'a, T: 'a> {

impl<'a, T: 'a> ChunksMut<'a, T> {
#[inline]
pub(super) fn new(slice: &'a mut [T], size: usize) -> Self {
pub(super) const fn new(slice: &'a mut [T], size: usize) -> Self {
Self { v: slice, chunk_size: size, _marker: PhantomData }
}
}
Expand Down Expand Up @@ -1863,7 +1863,7 @@ pub struct ChunksExact<'a, T: 'a> {

impl<'a, T> ChunksExact<'a, T> {
#[inline]
pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self {
pub(super) const fn new(slice: &'a [T], chunk_size: usize) -> Self {
let rem = slice.len() % chunk_size;
let fst_len = slice.len() - rem;
// SAFETY: 0 <= fst_len <= slice.len() by construction above
Expand Down Expand Up @@ -2043,7 +2043,7 @@ pub struct ChunksExactMut<'a, T: 'a> {

impl<'a, T> ChunksExactMut<'a, T> {
#[inline]
pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self {
pub(super) const fn new(slice: &'a mut [T], chunk_size: usize) -> Self {
let rem = slice.len() % chunk_size;
let fst_len = slice.len() - rem;
// SAFETY: 0 <= fst_len <= slice.len() by construction above
Expand Down Expand Up @@ -2210,7 +2210,7 @@ pub struct ArrayWindows<'a, T: 'a, const N: usize> {

impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> {
#[inline]
pub(super) fn new(slice: &'a [T]) -> Self {
pub(super) const fn new(slice: &'a [T]) -> Self {
let num_windows = slice.len().saturating_sub(N - 1);
Self { slice_head: slice.as_ptr(), num: num_windows, marker: PhantomData }
}
Expand Down Expand Up @@ -2334,8 +2334,10 @@ pub struct ArrayChunks<'a, T: 'a, const N: usize> {
}

impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
// #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
pub(super) fn new(slice: &'a [T]) -> Self {
pub(super) const fn new(slice: &'a [T]) -> Self {
let (array_slice, rem) = slice.as_chunks();
Self { iter: array_slice.iter(), rem }
}
Expand Down Expand Up @@ -2460,8 +2462,9 @@ pub struct ArrayChunksMut<'a, T: 'a, const N: usize> {
}

impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> {
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
pub(super) fn new(slice: &'a mut [T]) -> Self {
pub(super) const fn new(slice: &'a mut [T]) -> Self {
let (array_slice, rem) = slice.as_chunks_mut();
Self { iter: array_slice.iter_mut(), rem }
}
Expand Down Expand Up @@ -2579,7 +2582,7 @@ pub struct RChunks<'a, T: 'a> {

impl<'a, T: 'a> RChunks<'a, T> {
#[inline]
pub(super) fn new(slice: &'a [T], size: usize) -> Self {
pub(super) const fn new(slice: &'a [T], size: usize) -> Self {
Self { v: slice, chunk_size: size }
}
}
Expand Down Expand Up @@ -2759,7 +2762,7 @@ pub struct RChunksMut<'a, T: 'a> {

impl<'a, T: 'a> RChunksMut<'a, T> {
#[inline]
pub(super) fn new(slice: &'a mut [T], size: usize) -> Self {
pub(super) const fn new(slice: &'a mut [T], size: usize) -> Self {
Self { v: slice, chunk_size: size, _marker: PhantomData }
}
}
Expand Down Expand Up @@ -2950,7 +2953,7 @@ pub struct RChunksExact<'a, T: 'a> {

impl<'a, T> RChunksExact<'a, T> {
#[inline]
pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self {
pub(super) const fn new(slice: &'a [T], chunk_size: usize) -> Self {
let rem = slice.len() % chunk_size;
// SAFETY: 0 <= rem <= slice.len() by construction above
let (fst, snd) = unsafe { slice.split_at_unchecked(rem) };
Expand All @@ -2976,7 +2979,8 @@ impl<'a, T> RChunksExact<'a, T> {
/// ```
#[must_use]
#[stable(feature = "rchunks", since = "1.31.0")]
pub fn remainder(&self) -> &'a [T] {
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
pub const fn remainder(&self) -> &'a [T] {
self.rem
}
}
Expand Down Expand Up @@ -3132,7 +3136,7 @@ pub struct RChunksExactMut<'a, T: 'a> {

impl<'a, T> RChunksExactMut<'a, T> {
#[inline]
pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self {
pub(super) const fn new(slice: &'a mut [T], chunk_size: usize) -> Self {
let rem = slice.len() % chunk_size;
// SAFETY: 0 <= rem <= slice.len() by construction above
let (fst, snd) = unsafe { slice.split_at_mut_unchecked(rem) };
Expand All @@ -3144,7 +3148,8 @@ impl<'a, T> RChunksExactMut<'a, T> {
/// elements.
#[must_use = "`self` will be dropped if the result is not used"]
#[stable(feature = "rchunks", since = "1.31.0")]
pub fn into_remainder(self) -> &'a mut [T] {
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
pub const fn into_remainder(self) -> &'a mut [T] {
self.rem
}
}
Expand Down Expand Up @@ -3308,7 +3313,7 @@ pub struct ChunkBy<'a, T: 'a, P> {

#[stable(feature = "slice_group_by", since = "1.77.0")]
impl<'a, T: 'a, P> ChunkBy<'a, T, P> {
pub(super) fn new(slice: &'a [T], predicate: P) -> Self {
pub(super) const fn new(slice: &'a [T], predicate: P) -> Self {
ChunkBy { slice, predicate }
}
}
Expand Down Expand Up @@ -3395,7 +3400,7 @@ pub struct ChunkByMut<'a, T: 'a, P> {

#[stable(feature = "slice_group_by", since = "1.77.0")]
impl<'a, T: 'a, P> ChunkByMut<'a, T, P> {
pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self {
pub(super) const fn new(slice: &'a mut [T], predicate: P) -> Self {
ChunkByMut { slice, predicate }
}
}
Expand Down
48 changes: 32 additions & 16 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,9 +1043,10 @@ impl<T> [T] {
/// assert_eq!(iterator.next(), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[rustc_diagnostic_item = "slice_iter"]
pub fn iter(&self) -> Iter<'_, T> {
pub const fn iter(&self) -> Iter<'_, T> {
Iter::new(self)
}

Expand All @@ -1062,9 +1063,10 @@ impl<T> [T] {
/// }
/// assert_eq!(x, &[3, 4, 6]);
/// ```
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
pub const fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut::new(self)
}

Expand Down Expand Up @@ -1116,9 +1118,10 @@ impl<T> [T] {
/// assert_eq!(array, ['s', 't', ' ', '2', '0', '1', '5', 'u', 'R']);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn windows(&self, size: usize) -> Windows<'_, T> {
pub const fn windows(&self, size: usize) -> Windows<'_, T> {
let size = NonZero::new(size).expect("window size must be non-zero");
Windows::new(self, size)
}
Expand Down Expand Up @@ -1151,9 +1154,10 @@ impl<T> [T] {
/// [`chunks_exact`]: slice::chunks_exact
/// [`rchunks`]: slice::rchunks
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> {
pub const fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
Chunks::new(self, chunk_size)
}
Expand Down Expand Up @@ -1190,9 +1194,10 @@ impl<T> [T] {
/// [`chunks_exact_mut`]: slice::chunks_exact_mut
/// [`rchunks_mut`]: slice::rchunks_mut
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> {
pub const fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksMut::new(self, chunk_size)
}
Expand Down Expand Up @@ -1228,9 +1233,10 @@ impl<T> [T] {
/// [`chunks`]: slice::chunks
/// [`rchunks_exact`]: slice::rchunks_exact
#[stable(feature = "chunks_exact", since = "1.31.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
pub const fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksExact::new(self, chunk_size)
}
Expand Down Expand Up @@ -1271,9 +1277,10 @@ impl<T> [T] {
/// [`chunks_mut`]: slice::chunks_mut
/// [`rchunks_exact_mut`]: slice::rchunks_exact_mut
#[stable(feature = "chunks_exact", since = "1.31.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
pub const fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksExactMut::new(self, chunk_size)
}
Expand Down Expand Up @@ -1429,9 +1436,10 @@ impl<T> [T] {
///
/// [`chunks_exact`]: slice::chunks_exact
#[unstable(feature = "array_chunks", issue = "74985")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
pub const fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
assert!(N != 0, "chunk size must be non-zero");
ArrayChunks::new(self)
}
Expand Down Expand Up @@ -1592,9 +1600,10 @@ impl<T> [T] {
///
/// [`chunks_exact_mut`]: slice::chunks_exact_mut
#[unstable(feature = "array_chunks", issue = "74985")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> {
pub const fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> {
assert!(N != 0, "chunk size must be non-zero");
ArrayChunksMut::new(self)
}
Expand Down Expand Up @@ -1625,9 +1634,10 @@ impl<T> [T] {
///
/// [`windows`]: slice::windows
#[unstable(feature = "array_windows", issue = "75027")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
pub const fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
assert!(N != 0, "window size must be non-zero");
ArrayWindows::new(self)
}
Expand Down Expand Up @@ -1660,9 +1670,10 @@ impl<T> [T] {
/// [`rchunks_exact`]: slice::rchunks_exact
/// [`chunks`]: slice::chunks
#[stable(feature = "rchunks", since = "1.31.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {
pub const fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
RChunks::new(self, chunk_size)
}
Expand Down Expand Up @@ -1699,9 +1710,10 @@ impl<T> [T] {
/// [`rchunks_exact_mut`]: slice::rchunks_exact_mut
/// [`chunks_mut`]: slice::chunks_mut
#[stable(feature = "rchunks", since = "1.31.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> {
pub const fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksMut::new(self, chunk_size)
}
Expand Down Expand Up @@ -1739,9 +1751,10 @@ impl<T> [T] {
/// [`rchunks`]: slice::rchunks
/// [`chunks_exact`]: slice::chunks_exact
#[stable(feature = "rchunks", since = "1.31.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {
pub const fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksExact::new(self, chunk_size)
}
Expand Down Expand Up @@ -1783,9 +1796,10 @@ impl<T> [T] {
/// [`rchunks_mut`]: slice::rchunks_mut
/// [`chunks_exact_mut`]: slice::chunks_exact_mut
#[stable(feature = "rchunks", since = "1.31.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
#[track_caller]
pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {
pub const fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksExactMut::new(self, chunk_size)
}
Expand Down Expand Up @@ -1823,8 +1837,9 @@ impl<T> [T] {
/// assert_eq!(iter.next(), None);
/// ```
#[stable(feature = "slice_group_by", since = "1.77.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
pub fn chunk_by<F>(&self, pred: F) -> ChunkBy<'_, T, F>
pub const fn chunk_by<F>(&self, pred: F) -> ChunkBy<'_, T, F>
where
F: FnMut(&T, &T) -> bool,
{
Expand Down Expand Up @@ -1864,8 +1879,9 @@ impl<T> [T] {
/// assert_eq!(iter.next(), None);
/// ```
#[stable(feature = "slice_group_by", since = "1.77.0")]
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
#[inline]
pub fn chunk_by_mut<F>(&mut self, pred: F) -> ChunkByMut<'_, T, F>
pub const fn chunk_by_mut<F>(&mut self, pred: F) -> ChunkByMut<'_, T, F>
where
F: FnMut(&T, &T) -> bool,
{
Expand Down
Loading
Loading