Skip to content

Commit 8e8cac3

Browse files
committed
Add an internal slice::NonNullIter
1 parent bf4256a commit 8e8cac3

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
@@ -138,13 +138,23 @@ impl<'a, T> Iter<'a, T> {
138138
// SAFETY: the type invariant guarantees the pointer represents a valid reference
139139
unsafe { p.as_ref() }
140140
}
141+
}
141142

142-
fn empty() -> Self {
143+
#[stable(feature = "default_iters", since = "1.70.0")]
144+
impl<T> Default for Iter<'_, T> {
145+
/// Creates an empty slice iterator.
146+
///
147+
/// ```
148+
/// # use core::slice::Iter;
149+
/// let iter: Iter<'_, u8> = Default::default();
150+
/// assert_eq!(iter.len(), 0);
151+
/// ```
152+
fn default() -> Self {
143153
(&[]).into_iter()
144154
}
145155
}
146156

147-
iterator! {struct Iter -> *const T, &'a T, {
157+
iterator! {struct Iter<'a, T> => *const T, &'a T, {
148158
fn is_sorted_by<F>(self, mut compare: F) -> bool
149159
where
150160
Self: Sized,
@@ -368,8 +378,18 @@ impl<'a, T> IterMut<'a, T> {
368378
// SAFETY: the type invariant guarantees the pointer represents a valid item
369379
unsafe { p.as_mut() }
370380
}
381+
}
371382

372-
fn empty() -> Self {
383+
#[stable(feature = "default_iters", since = "1.70.0")]
384+
impl<T> Default for IterMut<'_, T> {
385+
/// Creates an empty slice iterator.
386+
///
387+
/// ```
388+
/// # use core::slice::IterMut;
389+
/// let iter: IterMut<'_, u8> = Default::default();
390+
/// assert_eq!(iter.len(), 0);
391+
/// ```
392+
fn default() -> Self {
373393
(&mut []).into_iter()
374394
}
375395
}
@@ -389,7 +409,85 @@ impl<T> AsRef<[T]> for IterMut<'_, T> {
389409
// }
390410
// }
391411

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

394492
/// An internal abstraction over the splitting iterators, so that
395493
/// 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
@@ -138,8 +139,9 @@ macro_rules! iterator {
138139
}
139140
}
140141

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

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

158161
#[inline]
@@ -389,8 +392,9 @@ macro_rules! iterator {
389392
$($extra)*
390393
}
391394

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

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

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

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

library/core/src/slice/mod.rs

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

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

0 commit comments

Comments
 (0)