Skip to content

Commit 0883848

Browse files
authored
Rollup merge of #92284 - the8472:simplify-advance-by, r=scottmcm
Change advance(_back)_by to return the remainder instead of the number of processed elements When advance_by can't advance the iterator by the number of requested elements it now returns the amount by which it couldn't be advanced instead of the amount by which it did. This simplifies adapters like chain, flatten or cycle because the remainder doesn't have to be calculated as the difference between requested steps and completed steps anymore. Additionally switching from `Result<(), usize>` to `Result<(), NonZeroUsize>` reduces the size of the result and makes converting from/to a usize representing the number of remaining steps cheap.
2 parents 857b631 + 4180793 commit 0883848

32 files changed

+383
-326
lines changed

Diff for: library/alloc/src/collections/vec_deque/into_iter.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::iter::{FusedIterator, TrustedLen};
2+
use core::num::NonZeroUsize;
23
use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr};
34

45
use crate::alloc::{Allocator, Global};
@@ -54,15 +55,16 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
5455
}
5556

5657
#[inline]
57-
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
58-
if self.inner.len < n {
59-
let len = self.inner.len;
58+
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
59+
let len = self.inner.len;
60+
let rem = if len < n {
6061
self.inner.clear();
61-
Err(len)
62+
n - len
6263
} else {
6364
self.inner.drain(..n);
64-
Ok(())
65-
}
65+
0
66+
};
67+
NonZeroUsize::new(rem).map_or(Ok(()), Err)
6668
}
6769

6870
#[inline]
@@ -182,15 +184,16 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
182184
}
183185

184186
#[inline]
185-
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
187+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
186188
let len = self.inner.len;
187-
if len >= n {
188-
self.inner.truncate(len - n);
189-
Ok(())
190-
} else {
189+
let rem = if len < n {
191190
self.inner.clear();
192-
Err(len)
193-
}
191+
n - len
192+
} else {
193+
self.inner.truncate(len - n);
194+
0
195+
};
196+
NonZeroUsize::new(rem).map_or(Ok(()), Err)
194197
}
195198

196199
fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R

Diff for: library/alloc/src/collections/vec_deque/iter.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
2+
use core::num::NonZeroUsize;
23
use core::ops::Try;
34
use core::{fmt, mem, slice};
45

@@ -55,13 +56,15 @@ impl<'a, T> Iterator for Iter<'a, T> {
5556
}
5657
}
5758

58-
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
59-
let m = match self.i1.advance_by(n) {
60-
Ok(_) => return Ok(()),
61-
Err(m) => m,
62-
};
63-
mem::swap(&mut self.i1, &mut self.i2);
64-
self.i1.advance_by(n - m).map_err(|o| o + m)
59+
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
60+
let remaining = self.i1.advance_by(n);
61+
match remaining {
62+
Ok(()) => return Ok(()),
63+
Err(n) => {
64+
mem::swap(&mut self.i1, &mut self.i2);
65+
self.i1.advance_by(n.get())
66+
}
67+
}
6568
}
6669

6770
#[inline]
@@ -125,14 +128,14 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
125128
}
126129
}
127130

128-
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
129-
let m = match self.i2.advance_back_by(n) {
130-
Ok(_) => return Ok(()),
131-
Err(m) => m,
132-
};
133-
134-
mem::swap(&mut self.i1, &mut self.i2);
135-
self.i2.advance_back_by(n - m).map_err(|o| m + o)
131+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
132+
match self.i2.advance_back_by(n) {
133+
Ok(()) => return Ok(()),
134+
Err(n) => {
135+
mem::swap(&mut self.i1, &mut self.i2);
136+
self.i2.advance_back_by(n.get())
137+
}
138+
}
136139
}
137140

138141
fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc

Diff for: library/alloc/src/collections/vec_deque/iter_mut.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
2+
use core::num::NonZeroUsize;
23
use core::ops::Try;
34
use core::{fmt, mem, slice};
45

@@ -47,13 +48,14 @@ impl<'a, T> Iterator for IterMut<'a, T> {
4748
}
4849
}
4950

50-
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
51-
let m = match self.i1.advance_by(n) {
52-
Ok(_) => return Ok(()),
53-
Err(m) => m,
54-
};
55-
mem::swap(&mut self.i1, &mut self.i2);
56-
self.i1.advance_by(n - m).map_err(|o| o + m)
51+
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
52+
match self.i1.advance_by(n) {
53+
Ok(()) => return Ok(()),
54+
Err(remaining) => {
55+
mem::swap(&mut self.i1, &mut self.i2);
56+
self.i1.advance_by(remaining.get())
57+
}
58+
}
5759
}
5860

5961
#[inline]
@@ -117,14 +119,14 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
117119
}
118120
}
119121

120-
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
121-
let m = match self.i2.advance_back_by(n) {
122-
Ok(_) => return Ok(()),
123-
Err(m) => m,
124-
};
125-
126-
mem::swap(&mut self.i1, &mut self.i2);
127-
self.i2.advance_back_by(n - m).map_err(|o| m + o)
122+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
123+
match self.i2.advance_back_by(n) {
124+
Ok(()) => return Ok(()),
125+
Err(remaining) => {
126+
mem::swap(&mut self.i1, &mut self.i2);
127+
self.i2.advance_back_by(remaining.get())
128+
}
129+
}
128130
}
129131

130132
fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc

Diff for: library/alloc/src/vec/into_iter.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use core::iter::{
1111
};
1212
use core::marker::PhantomData;
1313
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
14+
use core::num::NonZeroUsize;
1415
#[cfg(not(no_global_oom_handling))]
1516
use core::ops::Deref;
1617
use core::ptr::{self, NonNull};
@@ -213,7 +214,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
213214
}
214215

215216
#[inline]
216-
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
217+
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
217218
let step_size = self.len().min(n);
218219
let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size);
219220
if T::IS_ZST {
@@ -227,10 +228,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
227228
unsafe {
228229
ptr::drop_in_place(to_drop);
229230
}
230-
if step_size < n {
231-
return Err(step_size);
232-
}
233-
Ok(())
231+
NonZeroUsize::new(n - step_size).map_or(Ok(()), Err)
234232
}
235233

236234
#[inline]
@@ -313,7 +311,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
313311
}
314312

315313
#[inline]
316-
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
314+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
317315
let step_size = self.len().min(n);
318316
if T::IS_ZST {
319317
// SAFETY: same as for advance_by()
@@ -327,10 +325,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
327325
unsafe {
328326
ptr::drop_in_place(to_drop);
329327
}
330-
if step_size < n {
331-
return Err(step_size);
332-
}
333-
Ok(())
328+
NonZeroUsize::new(n - step_size).map_or(Ok(()), Err)
334329
}
335330
}
336331

Diff for: library/alloc/tests/vec.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use core::alloc::{Allocator, Layout};
2+
use core::assert_eq;
23
use core::iter::IntoIterator;
4+
use core::num::NonZeroUsize;
35
use core::ptr::NonNull;
46
use std::alloc::System;
57
use std::assert_matches::assert_matches;
@@ -1062,21 +1064,21 @@ fn test_into_iter_leak() {
10621064

10631065
#[test]
10641066
fn test_into_iter_advance_by() {
1065-
let mut i = [1, 2, 3, 4, 5].into_iter();
1066-
i.advance_by(0).unwrap();
1067-
i.advance_back_by(0).unwrap();
1067+
let mut i = vec![1, 2, 3, 4, 5].into_iter();
1068+
assert_eq!(i.advance_by(0), Ok(()));
1069+
assert_eq!(i.advance_back_by(0), Ok(()));
10681070
assert_eq!(i.as_slice(), [1, 2, 3, 4, 5]);
10691071

1070-
i.advance_by(1).unwrap();
1071-
i.advance_back_by(1).unwrap();
1072+
assert_eq!(i.advance_by(1), Ok(()));
1073+
assert_eq!(i.advance_back_by(1), Ok(()));
10721074
assert_eq!(i.as_slice(), [2, 3, 4]);
10731075

1074-
assert_eq!(i.advance_back_by(usize::MAX), Err(3));
1076+
assert_eq!(i.advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 3).unwrap()));
10751077

1076-
assert_eq!(i.advance_by(usize::MAX), Err(0));
1078+
assert_eq!(i.advance_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX).unwrap()));
10771079

1078-
i.advance_by(0).unwrap();
1079-
i.advance_back_by(0).unwrap();
1080+
assert_eq!(i.advance_by(0), Ok(()));
1081+
assert_eq!(i.advance_back_by(0), Ok(()));
10801082

10811083
assert_eq!(i.len(), 0);
10821084
}
@@ -1124,7 +1126,7 @@ fn test_into_iter_zst() {
11241126
for _ in vec![C; 5].into_iter().rev() {}
11251127

11261128
let mut it = vec![C, C].into_iter();
1127-
it.advance_by(1).unwrap();
1129+
assert_eq!(it.advance_by(1), Ok(()));
11281130
drop(it);
11291131

11301132
let mut it = vec![C, C].into_iter();

Diff for: library/alloc/tests/vec_deque.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::num::NonZeroUsize;
12
use std::assert_matches::assert_matches;
23
use std::collections::TryReserveErrorKind::*;
34
use std::collections::{vec_deque::Drain, VecDeque};
@@ -426,6 +427,28 @@ fn test_into_iter() {
426427
assert_eq!(it.next(), Some(7));
427428
assert_eq!(it.size_hint(), (5, Some(5)));
428429
}
430+
431+
// advance_by
432+
{
433+
let mut d = VecDeque::new();
434+
for i in 0..=4 {
435+
d.push_back(i);
436+
}
437+
for i in 6..=8 {
438+
d.push_front(i);
439+
}
440+
441+
let mut it = d.into_iter();
442+
assert_eq!(it.advance_by(1), Ok(()));
443+
assert_eq!(it.next(), Some(7));
444+
assert_eq!(it.advance_back_by(1), Ok(()));
445+
assert_eq!(it.next_back(), Some(3));
446+
447+
let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter();
448+
assert_eq!(it.advance_by(10), Err(NonZeroUsize::new(5).unwrap()));
449+
let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter();
450+
assert_eq!(it.advance_back_by(10), Err(NonZeroUsize::new(5).unwrap()));
451+
}
429452
}
430453

431454
#[test]

Diff for: library/core/src/array/iter.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Defines the `IntoIter` owned iterator for arrays.
22
3+
use crate::num::NonZeroUsize;
34
use crate::{
45
fmt,
56
iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
@@ -284,20 +285,19 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
284285
self.next_back()
285286
}
286287

287-
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
288-
let original_len = self.len();
289-
288+
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
290289
// This also moves the start, which marks them as conceptually "dropped",
291290
// so if anything goes bad then our drop impl won't double-free them.
292291
let range_to_drop = self.alive.take_prefix(n);
292+
let remaining = n - range_to_drop.len();
293293

294294
// SAFETY: These elements are currently initialized, so it's fine to drop them.
295295
unsafe {
296296
let slice = self.data.get_unchecked_mut(range_to_drop);
297297
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
298298
}
299299

300-
if n > original_len { Err(original_len) } else { Ok(()) }
300+
NonZeroUsize::new(remaining).map_or(Ok(()), Err)
301301
}
302302
}
303303

@@ -334,20 +334,19 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
334334
})
335335
}
336336

337-
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
338-
let original_len = self.len();
339-
337+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
340338
// This also moves the end, which marks them as conceptually "dropped",
341339
// so if anything goes bad then our drop impl won't double-free them.
342340
let range_to_drop = self.alive.take_suffix(n);
341+
let remaining = n - range_to_drop.len();
343342

344343
// SAFETY: These elements are currently initialized, so it's fine to drop them.
345344
unsafe {
346345
let slice = self.data.get_unchecked_mut(range_to_drop);
347346
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
348347
}
349348

350-
if n > original_len { Err(original_len) } else { Ok(()) }
349+
NonZeroUsize::new(remaining).map_or(Ok(()), Err)
351350
}
352351
}
353352

Diff for: library/core/src/iter/adapters/by_ref_sized.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::num::NonZeroUsize;
12
use crate::ops::{NeverShortCircuit, Try};
23

34
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
@@ -26,7 +27,7 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
2627
}
2728

2829
#[inline]
29-
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
30+
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
3031
I::advance_by(self.0, n)
3132
}
3233

@@ -62,7 +63,7 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
6263
}
6364

6465
#[inline]
65-
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
66+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
6667
I::advance_back_by(self.0, n)
6768
}
6869

0 commit comments

Comments
 (0)