Skip to content

Commit 5941a69

Browse files
committed
Add an internal slice::NonNullIter
1 parent 58f8939 commit 5941a69

File tree

3 files changed

+121
-26
lines changed

3 files changed

+121
-26
lines changed

library/core/src/slice/iter.rs

+104-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,85 @@ 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(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 it's sound to `offset` through it.
454+
/// - All those elements must be readable
455+
/// - The caller must ensure both as long as the iterator is in use.
456+
#[unstable(feature = "slice_non_null_iter", issue = "none")]
457+
#[inline]
458+
pub unsafe fn from_parts(ptr: NonNull<T>, len: usize) -> Self {
459+
// SAFETY: There are several things here:
460+
//
461+
// `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid
462+
// reference thus it is non-NUL and safe to use and pass to
463+
// `NonNull::new_unchecked` .
464+
//
465+
// Adding `slice.len()` to the starting pointer gives a pointer
466+
// at the end of `slice`. `end` will never be dereferenced, only checked
467+
// for direct pointer equality with `ptr` to check if the iterator is
468+
// done.
469+
//
470+
// In the case of a ZST, the end pointer is just the length. It's never
471+
// used as a pointer at all, and thus it's fine to have no provenance.
472+
//
473+
// See the `next_unchecked!` and `is_empty!` macros as well as the
474+
// `post_inc_start` method for more information.
475+
unsafe {
476+
let end_or_len =
477+
if T::IS_ZST { without_provenance_mut(len) } else { ptr.as_ptr().add(len) };
478+
479+
Self { ptr, end_or_len }
480+
}
481+
}
482+
483+
#[inline]
484+
unsafe fn non_null_to_item(p: NonNull<T>) -> <Self as Iterator>::Item {
485+
p
486+
}
487+
}
488+
489+
iterator! {struct NonNullIter<T> => *const T, NonNull<T>, {}}
390490

391491
/// An internal abstraction over the splitting iterators, so that
392492
/// 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
@@ -136,8 +137,9 @@ macro_rules! iterator {
136137
}
137138
}
138139

140+
#[allow(unused_lifetimes)]
139141
#[stable(feature = "rust1", since = "1.0.0")]
140-
impl<T> ExactSizeIterator for $name<'_, T> {
142+
impl<'a, T> ExactSizeIterator for $name {
141143
#[inline(always)]
142144
fn len(&self) -> usize {
143145
len!(self)
@@ -149,8 +151,9 @@ macro_rules! iterator {
149151
}
150152
}
151153

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

156159
#[inline]
@@ -387,8 +390,9 @@ macro_rules! iterator {
387390
$($extra)*
388391
}
389392

393+
#[allow(unused_lifetimes)]
390394
#[stable(feature = "rust1", since = "1.0.0")]
391-
impl<'a, T> DoubleEndedIterator for $name<'a, T> {
395+
impl<'a, T> DoubleEndedIterator for $name {
392396
#[inline]
393397
fn next_back(&mut self) -> Option<$elem> {
394398
// could be implemented with slices, but this avoids bounds checks
@@ -430,13 +434,16 @@ macro_rules! iterator {
430434
}
431435
}
432436

437+
#[allow(unused_lifetimes)]
433438
#[stable(feature = "fused", since = "1.26.0")]
434-
impl<T> FusedIterator for $name<'_, T> {}
439+
impl<'a, T> FusedIterator for $name {}
435440

441+
#[allow(unused_lifetimes)]
436442
#[unstable(feature = "trusted_len", issue = "37572")]
437-
unsafe impl<T> TrustedLen for $name<'_, T> {}
443+
unsafe impl<'a, T> TrustedLen for $name {}
438444

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

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)