Skip to content

Commit 2b14ecc

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 1b3a329 commit 2b14ecc

File tree

2 files changed

+44
-20
lines changed

2 files changed

+44
-20
lines changed

library/core/src/slice/iter.rs

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

@@ -126,11 +126,22 @@ impl<'a, T> Iter<'a, T> {
126126
#[stable(feature = "iter_to_slice", since = "1.4.0")]
127127
#[inline]
128128
pub fn as_slice(&self) -> &'a [T] {
129-
self.make_slice()
129+
// SAFETY: the type invariant guarantees the pointer represents a valid slice
130+
unsafe { self.make_nonnull_slice().as_ref() }
131+
}
132+
133+
#[inline]
134+
unsafe fn non_null_to_item(p: NonNull<T>) -> <Self as Iterator>::Item {
135+
// SAFETY: the type invariant guarantees the pointer represents a valid reference
136+
unsafe { p.as_ref() }
137+
}
138+
139+
fn empty() -> Self {
140+
(&[]).into_iter()
130141
}
131142
}
132143

133-
iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, {
144+
iterator! {struct Iter -> *const T, &'a T, {
134145
fn is_sorted_by<F>(self, mut compare: F) -> bool
135146
where
136147
Self: Sized,
@@ -198,7 +209,7 @@ pub struct IterMut<'a, T: 'a> {
198209
#[stable(feature = "core_impl_debug", since = "1.9.0")]
199210
impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
200211
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201-
f.debug_tuple("IterMut").field(&self.make_slice()).finish()
212+
f.debug_tuple("IterMut").field(&self.make_shortlived_slice()).finish()
202213
}
203214
}
204215

@@ -304,7 +315,8 @@ impl<'a, T> IterMut<'a, T> {
304315
#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
305316
#[inline]
306317
pub fn as_slice(&self) -> &[T] {
307-
self.make_slice()
318+
// SAFETY: the type invariant guarantees the pointer represents a valid slice
319+
unsafe { self.make_nonnull_slice().as_ref() }
308320
}
309321

310322
/// Views the underlying data as a mutable subslice of the original data.
@@ -347,6 +359,16 @@ impl<'a, T> IterMut<'a, T> {
347359
// for `from_raw_parts_mut` are fulfilled.
348360
unsafe { from_raw_parts_mut(self.ptr.as_ptr(), len!(self)) }
349361
}
362+
363+
#[inline]
364+
unsafe fn non_null_to_item(mut p: NonNull<T>) -> <Self as Iterator>::Item {
365+
// SAFETY: the type invariant guarantees the pointer represents a valid item
366+
unsafe { p.as_mut() }
367+
}
368+
369+
fn empty() -> Self {
370+
(&mut []).into_iter()
371+
}
350372
}
351373

352374
#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
@@ -364,7 +386,7 @@ impl<T> AsRef<[T]> for IterMut<'_, T> {
364386
// }
365387
// }
366388

367-
iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, as_mut, {}}
389+
iterator! {struct IterMut -> *mut T, &'a mut T, {}}
368390

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

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

+16-14
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,21 @@ 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 we can force a shorter
93+
// lifetime than `'a` to make this safe to call.
94+
unsafe { self.make_nonnull_slice().as_ref() }
9395
}
9496

9597
// Helper function for moving the start of the iterator forwards by `offset` elements,
@@ -227,7 +229,7 @@ macro_rules! iterator {
227229
loop {
228230
// SAFETY: the loop iterates `i in 0..len`, which always is in bounds of
229231
// the slice allocation
230-
acc = f(acc, unsafe { & $( $mut_ )? *self.ptr.add(i).as_ptr() });
232+
acc = f(acc, unsafe { Self::non_null_to_item(self.ptr.add(i)) });
231233
// SAFETY: `i` can't overflow since it'll only reach usize::MAX if the
232234
// slice had that length, in which case we'll break out of the loop
233235
// after the increment
@@ -378,7 +380,7 @@ macro_rules! iterator {
378380
// that will access this subslice are called, so it is valid
379381
// for the returned reference to be mutable in the case of
380382
// `IterMut`
381-
unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) }
383+
unsafe { Self::non_null_to_item(self.ptr.add(idx)) }
382384
}
383385

384386
$($extra)*
@@ -438,7 +440,7 @@ macro_rules! iterator {
438440
unsafe fn next_unchecked(&mut self) -> $elem {
439441
// SAFETY: The caller promised there's at least one more item.
440442
unsafe {
441-
self.post_inc_start(1).$into_ref()
443+
Self::non_null_to_item(self.post_inc_start(1))
442444
}
443445
}
444446
}
@@ -453,7 +455,7 @@ macro_rules! iterator {
453455
/// assert_eq!(iter.len(), 0);
454456
/// ```
455457
fn default() -> Self {
456-
(& $( $mut_ )? []).into_iter()
458+
Self::empty()
457459
}
458460
}
459461
}

0 commit comments

Comments
 (0)