Skip to content

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)