Skip to content
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

Make slice iterator constructors unstably const #137738

Merged
merged 1 commit into from
Apr 3, 2025
Merged
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
@@ -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 =
@@ -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
@@ -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 }
}
}
@@ -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 }
}
}
@@ -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 }
}
}
@@ -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
@@ -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
@@ -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 }
}
@@ -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 }
}
@@ -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 }
}
@@ -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 }
}
}
@@ -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 }
}
}
@@ -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) };
@@ -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
}
}
@@ -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) };
@@ -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
}
}
@@ -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 }
}
}
@@ -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 }
}
}
48 changes: 32 additions & 16 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
@@ -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)
}

@@ -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)
}

@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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,
{
@@ -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,
{
Loading
Loading