Skip to content

Commit 84125b2

Browse files
committed
Specialize len for ExactSizeIterator with unmistakable size_hint
1 parent dc80ca7 commit 84125b2

File tree

15 files changed

+286
-89
lines changed

15 files changed

+286
-89
lines changed

library/alloc/src/collections/binary_heap.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
13421342

13431343
#[stable(feature = "rust1", since = "1.0.0")]
13441344
impl<T> ExactSizeIterator for Iter<'_, T> {
1345+
fn len(&self) -> usize {
1346+
self.iter.len()
1347+
}
1348+
13451349
fn is_empty(&self) -> bool {
13461350
self.iter.is_empty()
13471351
}
@@ -1395,6 +1399,10 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
13951399

13961400
#[stable(feature = "rust1", since = "1.0.0")]
13971401
impl<T> ExactSizeIterator for IntoIter<T> {
1402+
fn len(&self) -> usize {
1403+
self.iter.len()
1404+
}
1405+
13981406
fn is_empty(&self) -> bool {
13991407
self.iter.is_empty()
14001408
}
@@ -1452,7 +1460,11 @@ impl<T: Ord> Iterator for IntoIterSorted<T> {
14521460
}
14531461

14541462
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
1455-
impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {}
1463+
impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {
1464+
fn len(&self) -> usize {
1465+
self.inner.len()
1466+
}
1467+
}
14561468

14571469
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
14581470
impl<T: Ord> FusedIterator for IntoIterSorted<T> {}
@@ -1497,6 +1509,10 @@ impl<T> DoubleEndedIterator for Drain<'_, T> {
14971509

14981510
#[stable(feature = "drain", since = "1.6.0")]
14991511
impl<T> ExactSizeIterator for Drain<'_, T> {
1512+
fn len(&self) -> usize {
1513+
self.iter.len()
1514+
}
1515+
15001516
fn is_empty(&self) -> bool {
15011517
self.iter.is_empty()
15021518
}
@@ -1554,7 +1570,11 @@ impl<T: Ord> Iterator for DrainSorted<'_, T> {
15541570
}
15551571

15561572
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
1557-
impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {}
1573+
impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {
1574+
fn len(&self) -> usize {
1575+
self.inner.len()
1576+
}
1577+
}
15581578

15591579
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
15601580
impl<T: Ord> FusedIterator for DrainSorted<'_, T> {}

library/alloc/src/collections/linked_list.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,12 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
10701070
}
10711071

10721072
#[stable(feature = "rust1", since = "1.0.0")]
1073-
impl<T> ExactSizeIterator for Iter<'_, T> {}
1073+
impl<T> ExactSizeIterator for Iter<'_, T> {
1074+
#[inline]
1075+
fn len(&self) -> usize {
1076+
self.len
1077+
}
1078+
}
10741079

10751080
#[stable(feature = "fused", since = "1.26.0")]
10761081
impl<T> FusedIterator for Iter<'_, T> {}
@@ -1124,7 +1129,11 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
11241129
}
11251130

11261131
#[stable(feature = "rust1", since = "1.0.0")]
1127-
impl<T> ExactSizeIterator for IterMut<'_, T> {}
1132+
impl<T> ExactSizeIterator for IterMut<'_, T> {
1133+
fn len(&self) -> usize {
1134+
self.len
1135+
}
1136+
}
11281137

11291138
#[stable(feature = "fused", since = "1.26.0")]
11301139
impl<T> FusedIterator for IterMut<'_, T> {}
@@ -1803,7 +1812,11 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
18031812
}
18041813

18051814
#[stable(feature = "rust1", since = "1.0.0")]
1806-
impl<T> ExactSizeIterator for IntoIter<T> {}
1815+
impl<T> ExactSizeIterator for IntoIter<T> {
1816+
fn len(&self) -> usize {
1817+
self.list.len
1818+
}
1819+
}
18071820

18081821
#[stable(feature = "fused", since = "1.26.0")]
18091822
impl<T> FusedIterator for IntoIter<T> {}

library/alloc/src/collections/vec_deque/drain.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,14 @@ impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
136136
}
137137

138138
#[stable(feature = "drain", since = "1.6.0")]
139-
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {}
139+
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
140+
#[inline]
141+
fn len(&self) -> usize {
142+
let n = self.iter.len();
143+
debug_assert_eq!(self.size_hint(), (n, Some(n)));
144+
n
145+
}
146+
}
140147

141148
#[stable(feature = "fused", since = "1.26.0")]
142149
impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}

library/alloc/src/collections/vec_deque/into_iter.rs

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
6060

6161
#[stable(feature = "rust1", since = "1.0.0")]
6262
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
63+
#[inline]
64+
fn len(&self) -> usize {
65+
self.inner.len()
66+
}
67+
6368
fn is_empty(&self) -> bool {
6469
self.inner.is_empty()
6570
}

library/alloc/src/collections/vec_deque/iter.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
6767

6868
#[inline]
6969
fn size_hint(&self) -> (usize, Option<usize>) {
70-
let len = count(self.tail, self.head, self.ring.len());
70+
let len = self.len();
7171
(len, Some(len))
7272
}
7373

@@ -113,7 +113,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
113113
}
114114

115115
fn nth(&mut self, n: usize) -> Option<Self::Item> {
116-
if n >= count(self.tail, self.head, self.ring.len()) {
116+
if n >= self.len() {
117117
self.tail = self.head;
118118
None
119119
} else {
@@ -197,6 +197,11 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
197197

198198
#[stable(feature = "rust1", since = "1.0.0")]
199199
impl<T> ExactSizeIterator for Iter<'_, T> {
200+
#[inline]
201+
fn len(&self) -> usize {
202+
count(self.tail, self.head, self.ring.len())
203+
}
204+
200205
fn is_empty(&self) -> bool {
201206
self.head == self.tail
202207
}

library/alloc/src/collections/vec_deque/iter_mut.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
6868

6969
#[inline]
7070
fn size_hint(&self) -> (usize, Option<usize>) {
71-
let len = count(self.tail, self.head, self.ring.len());
71+
let len = self.len();
7272
(len, Some(len))
7373
}
7474

@@ -85,7 +85,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
8585
}
8686

8787
fn nth(&mut self, n: usize) -> Option<Self::Item> {
88-
if n >= count(self.tail, self.head, self.ring.len()) {
88+
if n >= self.len() {
8989
self.tail = self.head;
9090
None
9191
} else {
@@ -140,6 +140,11 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
140140

141141
#[stable(feature = "rust1", since = "1.0.0")]
142142
impl<T> ExactSizeIterator for IterMut<'_, T> {
143+
#[inline]
144+
fn len(&self) -> usize {
145+
count(self.tail, self.head, self.ring.len())
146+
}
147+
143148
fn is_empty(&self) -> bool {
144149
self.head == self.tail
145150
}

library/alloc/src/vec/drain.rs

+4
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
172172

173173
#[stable(feature = "drain", since = "1.6.0")]
174174
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
175+
fn len(&self) -> usize {
176+
self.iter.len()
177+
}
178+
175179
fn is_empty(&self) -> bool {
176180
self.iter.is_empty()
177181
}

library/alloc/src/vec/into_iter.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
166166

167167
#[inline]
168168
fn size_hint(&self) -> (usize, Option<usize>) {
169-
let exact = if mem::size_of::<T>() == 0 {
170-
self.end.addr().wrapping_sub(self.ptr.addr())
171-
} else {
172-
unsafe { self.end.sub_ptr(self.ptr) }
173-
};
169+
let exact = self.len();
174170
(exact, Some(exact))
175171
}
176172

@@ -265,6 +261,15 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
265261

266262
#[stable(feature = "rust1", since = "1.0.0")]
267263
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
264+
#[inline]
265+
fn len(&self) -> usize {
266+
if mem::size_of::<T>() == 0 {
267+
self.end.addr().wrapping_sub(self.ptr.addr())
268+
} else {
269+
unsafe { self.end.sub_ptr(self.ptr) }
270+
}
271+
}
272+
268273
fn is_empty(&self) -> bool {
269274
self.ptr == self.end
270275
}

library/alloc/src/vec/splice.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ impl<I: Iterator, A: Allocator> DoubleEndedIterator for Splice<'_, I, A> {
4848
}
4949

5050
#[stable(feature = "vec_splice", since = "1.21.0")]
51-
impl<I: Iterator, A: Allocator> ExactSizeIterator for Splice<'_, I, A> {}
51+
impl<I: Iterator, A: Allocator> ExactSizeIterator for Splice<'_, I, A> {
52+
fn len(&self) -> usize {
53+
let n = self.drain.len();
54+
debug_assert_eq!(self.size_hint(), (n, Some(n)));
55+
n
56+
}
57+
}
5258

5359
#[stable(feature = "vec_splice", since = "1.21.0")]
5460
impl<I: Iterator, A: Allocator> Drop for Splice<'_, I, A> {

library/core/src/ascii.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ impl DoubleEndedIterator for EscapeDefault {
129129
}
130130
}
131131
#[stable(feature = "rust1", since = "1.0.0")]
132-
impl ExactSizeIterator for EscapeDefault {}
132+
impl ExactSizeIterator for EscapeDefault {
133+
fn len(&self) -> usize {
134+
self.range.len()
135+
}
136+
}
133137
#[stable(feature = "fused", since = "1.26.0")]
134138
impl FusedIterator for EscapeDefault {}
135139

library/core/src/char/mod.rs

+30-6
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,13 @@ impl Iterator for EscapeDebug {
386386
}
387387

388388
#[stable(feature = "char_escape_debug", since = "1.20.0")]
389-
impl ExactSizeIterator for EscapeDebug {}
389+
impl ExactSizeIterator for EscapeDebug {
390+
fn len(&self) -> usize {
391+
let n = self.0.len();
392+
debug_assert_eq!(self.size_hint(), (n, Some(n)));
393+
n
394+
}
395+
}
390396

391397
#[stable(feature = "fused", since = "1.26.0")]
392398
impl FusedIterator for EscapeDebug {}
@@ -430,7 +436,13 @@ impl DoubleEndedIterator for ToLowercase {
430436
impl FusedIterator for ToLowercase {}
431437

432438
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
433-
impl ExactSizeIterator for ToLowercase {}
439+
impl ExactSizeIterator for ToLowercase {
440+
fn len(&self) -> usize {
441+
let n = self.0.len();
442+
debug_assert_eq!(self.size_hint(), (n, Some(n)));
443+
n
444+
}
445+
}
434446

435447
/// Returns an iterator that yields the uppercase equivalent of a `char`.
436448
///
@@ -464,7 +476,13 @@ impl DoubleEndedIterator for ToUppercase {
464476
impl FusedIterator for ToUppercase {}
465477

466478
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
467-
impl ExactSizeIterator for ToUppercase {}
479+
impl ExactSizeIterator for ToUppercase {
480+
fn len(&self) -> usize {
481+
let n = self.0.len();
482+
debug_assert_eq!(self.size_hint(), (n, Some(n)));
483+
n
484+
}
485+
}
468486

469487
#[derive(Debug, Clone)]
470488
enum CaseMappingIter {
@@ -509,13 +527,19 @@ impl Iterator for CaseMappingIter {
509527
}
510528

511529
fn size_hint(&self) -> (usize, Option<usize>) {
512-
let size = match self {
530+
let size = self.len();
531+
(size, Some(size))
532+
}
533+
}
534+
535+
impl CaseMappingIter {
536+
fn len(&self) -> usize {
537+
match self {
513538
CaseMappingIter::Three(..) => 3,
514539
CaseMappingIter::Two(..) => 2,
515540
CaseMappingIter::One(_) => 1,
516541
CaseMappingIter::Zero => 0,
517-
};
518-
(size, Some(size))
542+
}
519543
}
520544
}
521545

library/core/src/iter/traits/exact_size.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ pub trait ExactSizeIterator: Iterator {
102102
fn len(&self) -> usize {
103103
let (lower, upper) = self.size_hint();
104104
// Note: This assertion is overly defensive, but it checks the invariant
105-
// guaranteed by the trait. If this trait were rust-internal,
106-
// we could use debug_assert!; assert_eq! will check all Rust user
107-
// implementations too.
105+
// guaranteed by the trait in all Rust user implementations too.
106+
// If this trait were rust-internal, we could use debug_assert!, but
107+
// any implementation for which it matters can override `len`.
108108
assert_eq!(upper, Some(lower));
109109
lower
110110
}

0 commit comments

Comments
 (0)