Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit bf4256a

Browse files
committed
Replace various iterator! parameters with self calls
Rather than encoding things as method calls or token expansions. This isn't directly useful for Iter/IterMut, but sets this up for the next commit that adds another invocation of the macro.
1 parent cc8da78 commit bf4256a

File tree

2 files changed

+45
-20
lines changed

2 files changed

+45
-20
lines changed

library/core/src/slice/iter.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub struct Iter<'a, T: 'a> {
7878
#[stable(feature = "core_impl_debug", since = "1.9.0")]
7979
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
8080
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81-
f.debug_tuple("Iter").field(&self.as_slice()).finish()
81+
f.debug_tuple("Iter").field(&self.make_shortlived_slice()).finish()
8282
}
8383
}
8484

@@ -129,11 +129,22 @@ impl<'a, T> Iter<'a, T> {
129129
#[stable(feature = "iter_to_slice", since = "1.4.0")]
130130
#[inline]
131131
pub fn as_slice(&self) -> &'a [T] {
132-
self.make_slice()
132+
// SAFETY: the type invariant guarantees the pointer represents a valid slice
133+
unsafe { self.make_nonnull_slice().as_ref() }
134+
}
135+
136+
#[inline]
137+
unsafe fn non_null_to_item(p: NonNull<T>) -> <Self as Iterator>::Item {
138+
// SAFETY: the type invariant guarantees the pointer represents a valid reference
139+
unsafe { p.as_ref() }
140+
}
141+
142+
fn empty() -> Self {
143+
(&[]).into_iter()
133144
}
134145
}
135146

136-
iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, {
147+
iterator! {struct Iter -> *const T, &'a T, {
137148
fn is_sorted_by<F>(self, mut compare: F) -> bool
138149
where
139150
Self: Sized,
@@ -201,7 +212,7 @@ pub struct IterMut<'a, T: 'a> {
201212
#[stable(feature = "core_impl_debug", since = "1.9.0")]
202213
impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
203214
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204-
f.debug_tuple("IterMut").field(&self.make_slice()).finish()
215+
f.debug_tuple("IterMut").field(&self.make_shortlived_slice()).finish()
205216
}
206217
}
207218

@@ -307,7 +318,8 @@ impl<'a, T> IterMut<'a, T> {
307318
#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
308319
#[inline]
309320
pub fn as_slice(&self) -> &[T] {
310-
self.make_slice()
321+
// SAFETY: the type invariant guarantees the pointer represents a valid slice
322+
unsafe { self.make_nonnull_slice().as_ref() }
311323
}
312324

313325
/// Views the underlying data as a mutable subslice of the original data.
@@ -350,6 +362,16 @@ impl<'a, T> IterMut<'a, T> {
350362
// for `from_raw_parts_mut` are fulfilled.
351363
unsafe { from_raw_parts_mut(self.ptr.as_ptr(), len!(self)) }
352364
}
365+
366+
#[inline]
367+
unsafe fn non_null_to_item(mut p: NonNull<T>) -> <Self as Iterator>::Item {
368+
// SAFETY: the type invariant guarantees the pointer represents a valid item
369+
unsafe { p.as_mut() }
370+
}
371+
372+
fn empty() -> Self {
373+
(&mut []).into_iter()
374+
}
353375
}
354376

355377
#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
@@ -367,7 +389,7 @@ impl<T> AsRef<[T]> for IterMut<'_, T> {
367389
// }
368390
// }
369391

370-
iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, as_mut, {}}
392+
iterator! {struct IterMut -> *mut T, &'a mut T, {}}
371393

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

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

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ macro_rules! iterator {
6565
(
6666
struct $name:ident -> $ptr:ty,
6767
$elem:ty,
68-
$raw_mut:tt,
69-
{$( $mut_:tt )?},
70-
$into_ref:ident,
7168
{$($extra:tt)*}
7269
) => {
7370
impl<'a, T> $name<'a, T> {
@@ -80,16 +77,22 @@ macro_rules! iterator {
8077
unsafe fn next_back_unchecked(&mut self) -> $elem {
8178
// SAFETY: the caller promised it's not empty, so
8279
// the offsetting is in-bounds and there's an element to return.
83-
unsafe { self.pre_dec_end(1).$into_ref() }
80+
unsafe { Self::non_null_to_item(self.pre_dec_end(1)) }
8481
}
8582

8683
// Helper function for creating a slice from the iterator.
87-
#[inline(always)]
88-
fn make_slice(&self) -> &'a [T] {
89-
// SAFETY: the iterator was created from a slice with pointer
90-
// `self.ptr` and length `len!(self)`. This guarantees that all
91-
// the prerequisites for `from_raw_parts` are fulfilled.
92-
unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) }
84+
#[inline]
85+
pub(crate) fn make_nonnull_slice(&self) -> NonNull<[T]> {
86+
NonNull::slice_from_raw_parts(self.ptr, len!(self))
87+
}
88+
89+
#[inline]
90+
pub(crate) fn make_shortlived_slice<'b>(&'b self) -> &'b [T] {
91+
// SAFETY: Everything expanded with this macro is readable while
92+
// the iterator exists and is unchanged, so by tying this to the
93+
// shorter-than-`'a` self borrow we can make this safe to call.
94+
// (Elision would be fine here, but using `'b` for emphasis.)
95+
unsafe { self.make_nonnull_slice().as_ref() }
9396
}
9497

9598
// Helper function for moving the start of the iterator forwards by `offset` elements,
@@ -229,7 +232,7 @@ macro_rules! iterator {
229232
loop {
230233
// SAFETY: the loop iterates `i in 0..len`, which always is in bounds of
231234
// the slice allocation
232-
acc = f(acc, unsafe { & $( $mut_ )? *self.ptr.add(i).as_ptr() });
235+
acc = f(acc, unsafe { Self::non_null_to_item(self.ptr.add(i)) });
233236
// SAFETY: `i` can't overflow since it'll only reach usize::MAX if the
234237
// slice had that length, in which case we'll break out of the loop
235238
// after the increment
@@ -380,7 +383,7 @@ macro_rules! iterator {
380383
// that will access this subslice are called, so it is valid
381384
// for the returned reference to be mutable in the case of
382385
// `IterMut`
383-
unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) }
386+
unsafe { Self::non_null_to_item(self.ptr.add(idx)) }
384387
}
385388

386389
$($extra)*
@@ -440,7 +443,7 @@ macro_rules! iterator {
440443
unsafe fn next_unchecked(&mut self) -> $elem {
441444
// SAFETY: The caller promised there's at least one more item.
442445
unsafe {
443-
self.post_inc_start(1).$into_ref()
446+
Self::non_null_to_item(self.post_inc_start(1))
444447
}
445448
}
446449
}
@@ -455,7 +458,7 @@ macro_rules! iterator {
455458
/// assert_eq!(iter.len(), 0);
456459
/// ```
457460
fn default() -> Self {
458-
(& $( $mut_ )? []).into_iter()
461+
Self::empty()
459462
}
460463
}
461464
}

0 commit comments

Comments
 (0)