Skip to content

Commit 2bddad7

Browse files
committed
Add an internal slice::NonNullIter
1 parent 2b14ecc commit 2bddad7

File tree

3 files changed

+119
-26
lines changed

3 files changed

+119
-26
lines changed

library/core/src/slice/iter.rs

+102-4
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,24 @@ impl<'a, T> Iter<'a, T> {
135135
// SAFETY: the type invariant guarantees the pointer represents a valid reference
136136
unsafe { p.as_ref() }
137137
}
138+
}
138139

139-
fn empty() -> Self {
140+
#[allow(unused_lifetimes)]
141+
#[stable(feature = "default_iters", since = "1.70.0")]
142+
impl<T> Default for Iter<'_, T> {
143+
/// Creates an empty slice iterator.
144+
///
145+
/// ```
146+
/// # use core::slice::Iter;
147+
/// let iter: Iter<'_, u8> = Default::default();
148+
/// assert_eq!(iter.len(), 0);
149+
/// ```
150+
fn default() -> Self {
140151
(&[]).into_iter()
141152
}
142153
}
143154

144-
iterator! {struct Iter -> *const T, &'a T, {
155+
iterator! {struct Iter<'a, T> => *const T, &'a T, {
145156
fn is_sorted_by<F>(self, mut compare: F) -> bool
146157
where
147158
Self: Sized,
@@ -365,8 +376,19 @@ impl<'a, T> IterMut<'a, T> {
365376
// SAFETY: the type invariant guarantees the pointer represents a valid item
366377
unsafe { p.as_mut() }
367378
}
379+
}
368380

369-
fn empty() -> Self {
381+
#[allow(unused_lifetimes)]
382+
#[stable(feature = "default_iters", since = "1.70.0")]
383+
impl<T> Default for IterMut<'_, T> {
384+
/// Creates an empty slice iterator.
385+
///
386+
/// ```
387+
/// # use core::slice::IterMut;
388+
/// let iter: IterMut<'_, u8> = Default::default();
389+
/// assert_eq!(iter.len(), 0);
390+
/// ```
391+
fn default() -> Self {
370392
(&mut []).into_iter()
371393
}
372394
}
@@ -386,7 +408,83 @@ impl<T> AsRef<[T]> for IterMut<'_, T> {
386408
// }
387409
// }
388410

389-
iterator! {struct IterMut -> *mut T, &'a mut T, {}}
411+
iterator! {struct IterMut<'a, T> => *mut T, &'a mut T, {}}
412+
413+
/// Iterator over all the `NonNull<T>` pointers to the elements of a slice.
414+
#[unstable(feature = "slice_non_null_iter", issue = "none")]
415+
#[must_use = "iterators are lazy and do nothing unless consumed"]
416+
pub struct NonNullIter<T> {
417+
/// The pointer to the next element to return, or the past-the-end location
418+
/// if the iterator is empty.
419+
///
420+
/// This address will be used for all ZST elements, never changed.
421+
ptr: NonNull<T>,
422+
/// For non-ZSTs, the non-null pointer to the past-the-end element.
423+
///
424+
/// For ZSTs, this is `ptr::without_provenance_mut(len)`.
425+
end_or_len: *const T,
426+
}
427+
428+
#[unstable(feature = "slice_non_null_iter", issue = "none")]
429+
impl<T: fmt::Debug> fmt::Debug for NonNullIter<T> {
430+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
431+
f.debug_tuple("NonNullIter").field(&self.make_shortlived_slice()).finish()
432+
}
433+
}
434+
435+
impl<T> NonNullIter<T> {
436+
/// Turn an iterator giving `&T`s into one giving `NonNull<T>`s.
437+
#[unstable(feature = "slice_non_null_iter", issue = "none")]
438+
pub fn from_slice_iter(Iter { ptr, end_or_len, .. }: Iter<'_, T>) -> Self {
439+
Self { ptr, end_or_len }
440+
}
441+
442+
/// Turn an iterator giving `&mut T`s into one giving `NonNull<T>`s.
443+
#[unstable(feature = "slice_non_null_iter", issue = "none")]
444+
pub fn from_slice_iter_mut(IterMut { ptr, end_or_len, .. }: IterMut<'_, T>) -> Self {
445+
Self { ptr, end_or_len }
446+
}
447+
448+
/// Creates a new iterator over the `len` items starting at `ptr`
449+
///
450+
/// # Safety
451+
///
452+
/// `ptr` through `ptr.add(len)` must be a single allocated object
453+
/// such that that
454+
#[unstable(feature = "slice_non_null_iter", issue = "none")]
455+
#[inline]
456+
pub unsafe fn from_parts(ptr: NonNull<T>, len: usize) -> Self {
457+
// SAFETY: There are several things here:
458+
//
459+
// `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid
460+
// reference thus it is non-NUL and safe to use and pass to
461+
// `NonNull::new_unchecked` .
462+
//
463+
// Adding `slice.len()` to the starting pointer gives a pointer
464+
// at the end of `slice`. `end` will never be dereferenced, only checked
465+
// for direct pointer equality with `ptr` to check if the iterator is
466+
// done.
467+
//
468+
// In the case of a ZST, the end pointer is just the length. It's never
469+
// used as a pointer at all, and thus it's fine to have no provenance.
470+
//
471+
// See the `next_unchecked!` and `is_empty!` macros as well as the
472+
// `post_inc_start` method for more information.
473+
unsafe {
474+
let end_or_len =
475+
if T::IS_ZST { without_provenance_mut(len) } else { ptr.as_ptr().add(len) };
476+
477+
Self { ptr, end_or_len }
478+
}
479+
}
480+
481+
#[inline]
482+
unsafe fn non_null_to_item(p: NonNull<T>) -> <Self as Iterator>::Item {
483+
p
484+
}
485+
}
486+
487+
iterator! {struct NonNullIter<T> => *const T, NonNull<T>, {}}
390488

391489
/// An internal abstraction over the splitting iterators, so that
392490
/// splitn, splitn_mut etc can be implemented once.

library/core/src/slice/iter/macros.rs

+15-22
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ macro_rules! len {
6363
// The shared definition of the `Iter` and `IterMut` iterators
6464
macro_rules! iterator {
6565
(
66-
struct $name:ident -> $ptr:ty,
66+
struct $name:ty => $ptr:ty,
6767
$elem:ty,
6868
{$($extra:tt)*}
6969
) => {
70-
impl<'a, T> $name<'a, T> {
70+
#[allow(unused_lifetimes)]
71+
impl<'a, T> $name {
7172
/// Returns the last element and moves the end of the iterator backwards by 1.
7273
///
7374
/// # Safety
@@ -135,8 +136,9 @@ macro_rules! iterator {
135136
}
136137
}
137138

139+
#[allow(unused_lifetimes)]
138140
#[stable(feature = "rust1", since = "1.0.0")]
139-
impl<T> ExactSizeIterator for $name<'_, T> {
141+
impl<'a, T> ExactSizeIterator for $name {
140142
#[inline(always)]
141143
fn len(&self) -> usize {
142144
len!(self)
@@ -148,8 +150,9 @@ macro_rules! iterator {
148150
}
149151
}
150152

153+
#[allow(unused_lifetimes)]
151154
#[stable(feature = "rust1", since = "1.0.0")]
152-
impl<'a, T> Iterator for $name<'a, T> {
155+
impl<'a, T> Iterator for $name {
153156
type Item = $elem;
154157

155158
#[inline]
@@ -386,8 +389,9 @@ macro_rules! iterator {
386389
$($extra)*
387390
}
388391

392+
#[allow(unused_lifetimes)]
389393
#[stable(feature = "rust1", since = "1.0.0")]
390-
impl<'a, T> DoubleEndedIterator for $name<'a, T> {
394+
impl<'a, T> DoubleEndedIterator for $name {
391395
#[inline]
392396
fn next_back(&mut self) -> Option<$elem> {
393397
// could be implemented with slices, but this avoids bounds checks
@@ -429,13 +433,16 @@ macro_rules! iterator {
429433
}
430434
}
431435

436+
#[allow(unused_lifetimes)]
432437
#[stable(feature = "fused", since = "1.26.0")]
433-
impl<T> FusedIterator for $name<'_, T> {}
438+
impl<'a, T> FusedIterator for $name {}
434439

440+
#[allow(unused_lifetimes)]
435441
#[unstable(feature = "trusted_len", issue = "37572")]
436-
unsafe impl<T> TrustedLen for $name<'_, T> {}
442+
unsafe impl<'a, T> TrustedLen for $name {}
437443

438-
impl<'a, T> UncheckedIterator for $name<'a, T> {
444+
#[allow(unused_lifetimes)]
445+
impl<'a, T> UncheckedIterator for $name {
439446
#[inline]
440447
unsafe fn next_unchecked(&mut self) -> $elem {
441448
// SAFETY: The caller promised there's at least one more item.
@@ -444,20 +451,6 @@ macro_rules! iterator {
444451
}
445452
}
446453
}
447-
448-
#[stable(feature = "default_iters", since = "1.70.0")]
449-
impl<T> Default for $name<'_, T> {
450-
/// Creates an empty slice iterator.
451-
///
452-
/// ```
453-
#[doc = concat!("# use core::slice::", stringify!($name), ";")]
454-
#[doc = concat!("let iter: ", stringify!($name<'_, u8>), " = Default::default();")]
455-
/// assert_eq!(iter.len(), 0);
456-
/// ```
457-
fn default() -> Self {
458-
Self::empty()
459-
}
460-
}
461454
}
462455
}
463456

library/core/src/slice/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ mod specialize;
4646
#[doc(hidden)]
4747
pub use ascii::is_ascii_simple;
4848

49+
#[unstable(feature = "slice_non_null_iter", issue = "none")]
50+
pub use iter::NonNullIter;
4951
#[stable(feature = "rust1", since = "1.0.0")]
5052
pub use iter::{Chunks, ChunksMut, Windows};
5153
#[stable(feature = "rust1", since = "1.0.0")]

0 commit comments

Comments
 (0)