Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specialize len in ExactSizeIterator implementations #91998

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 22 additions & 2 deletions library/alloc/src/collections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for Iter<'_, T> {
fn len(&self) -> usize {
self.iter.len()
}

fn is_empty(&self) -> bool {
self.iter.is_empty()
}
Expand Down Expand Up @@ -1395,6 +1399,10 @@ impl<T> DoubleEndedIterator for IntoIter<T> {

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for IntoIter<T> {
fn len(&self) -> usize {
self.iter.len()
}

fn is_empty(&self) -> bool {
self.iter.is_empty()
}
Expand Down Expand Up @@ -1452,7 +1460,11 @@ impl<T: Ord> Iterator for IntoIterSorted<T> {
}

#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {}
impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {
fn len(&self) -> usize {
self.inner.len()
}
}

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

#[stable(feature = "drain", since = "1.6.0")]
impl<T> ExactSizeIterator for Drain<'_, T> {
fn len(&self) -> usize {
self.iter.len()
}

fn is_empty(&self) -> bool {
self.iter.is_empty()
}
Expand Down Expand Up @@ -1554,7 +1570,11 @@ impl<T: Ord> Iterator for DrainSorted<'_, T> {
}

#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {}
impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {
fn len(&self) -> usize {
self.inner.len()
}
}

#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
impl<T: Ord> FusedIterator for DrainSorted<'_, T> {}
Expand Down
19 changes: 16 additions & 3 deletions library/alloc/src/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,12 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for Iter<'_, T> {}
impl<T> ExactSizeIterator for Iter<'_, T> {
#[inline]
fn len(&self) -> usize {
self.len
}
}

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

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for IterMut<'_, T> {}
impl<T> ExactSizeIterator for IterMut<'_, T> {
fn len(&self) -> usize {
self.len
}
}

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

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for IntoIter<T> {}
impl<T> ExactSizeIterator for IntoIter<T> {
fn len(&self) -> usize {
self.list.len
}
}

#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}
Expand Down
9 changes: 8 additions & 1 deletion library/alloc/src/collections/vec_deque/drain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,14 @@ impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
}

#[stable(feature = "drain", since = "1.6.0")]
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {}
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
#[inline]
fn len(&self) -> usize {
let n = self.iter.len();
debug_assert_eq!(self.size_hint(), (n, Some(n)));
n
}
}

#[stable(feature = "fused", since = "1.26.0")]
impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}
5 changes: 5 additions & 0 deletions library/alloc/src/collections/vec_deque/into_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}

fn is_empty(&self) -> bool {
self.inner.is_empty()
}
Expand Down
9 changes: 7 additions & 2 deletions library/alloc/src/collections/vec_deque/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<'a, T> Iterator for Iter<'a, T> {

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

Expand Down Expand Up @@ -113,7 +113,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
}

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

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for Iter<'_, T> {
#[inline]
fn len(&self) -> usize {
count(self.tail, self.head, self.ring.len())
}

fn is_empty(&self) -> bool {
self.head == self.tail
}
Expand Down
9 changes: 7 additions & 2 deletions library/alloc/src/collections/vec_deque/iter_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {

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

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

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

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for IterMut<'_, T> {
#[inline]
fn len(&self) -> usize {
count(self.tail, self.head, self.ring.len())
}

fn is_empty(&self) -> bool {
self.head == self.tail
}
Expand Down
4 changes: 4 additions & 0 deletions library/alloc/src/vec/drain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {

#[stable(feature = "drain", since = "1.6.0")]
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
fn len(&self) -> usize {
self.iter.len()
}

fn is_empty(&self) -> bool {
self.iter.is_empty()
}
Expand Down
15 changes: 10 additions & 5 deletions library/alloc/src/vec/into_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let exact = if mem::size_of::<T>() == 0 {
self.end.addr().wrapping_sub(self.ptr.addr())
} else {
unsafe { self.end.sub_ptr(self.ptr) }
};
let exact = self.len();
(exact, Some(exact))
}

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

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
#[inline]
fn len(&self) -> usize {
if mem::size_of::<T>() == 0 {
self.end.addr().wrapping_sub(self.ptr.addr())
} else {
unsafe { self.end.sub_ptr(self.ptr) }
}
}

fn is_empty(&self) -> bool {
self.ptr == self.end
}
Expand Down
8 changes: 7 additions & 1 deletion library/alloc/src/vec/splice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ impl<I: Iterator, A: Allocator> DoubleEndedIterator for Splice<'_, I, A> {
}

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

#[stable(feature = "vec_splice", since = "1.21.0")]
impl<I: Iterator, A: Allocator> Drop for Splice<'_, I, A> {
Expand Down
6 changes: 5 additions & 1 deletion library/core/src/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ impl DoubleEndedIterator for EscapeDefault {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for EscapeDefault {}
impl ExactSizeIterator for EscapeDefault {
fn len(&self) -> usize {
self.range.len()
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDefault {}

Expand Down
36 changes: 30 additions & 6 deletions library/core/src/char/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,13 @@ impl Iterator for EscapeDebug {
}

#[stable(feature = "char_escape_debug", since = "1.20.0")]
impl ExactSizeIterator for EscapeDebug {}
impl ExactSizeIterator for EscapeDebug {
fn len(&self) -> usize {
let n = self.0.len();
debug_assert_eq!(self.size_hint(), (n, Some(n)));
n
}
}

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

#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
impl ExactSizeIterator for ToLowercase {}
impl ExactSizeIterator for ToLowercase {
fn len(&self) -> usize {
let n = self.0.len();
debug_assert_eq!(self.size_hint(), (n, Some(n)));
n
}
}

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

#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
impl ExactSizeIterator for ToUppercase {}
impl ExactSizeIterator for ToUppercase {
fn len(&self) -> usize {
let n = self.0.len();
debug_assert_eq!(self.size_hint(), (n, Some(n)));
n
}
}

#[derive(Debug, Clone)]
enum CaseMappingIter {
Expand Down Expand Up @@ -509,13 +527,19 @@ impl Iterator for CaseMappingIter {
}

fn size_hint(&self) -> (usize, Option<usize>) {
let size = match self {
let size = self.len();
(size, Some(size))
}
}

impl CaseMappingIter {
fn len(&self) -> usize {
match self {
CaseMappingIter::Three(..) => 3,
CaseMappingIter::Two(..) => 2,
CaseMappingIter::One(_) => 1,
CaseMappingIter::Zero => 0,
};
(size, Some(size))
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions library/core/src/iter/traits/exact_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ pub trait ExactSizeIterator: Iterator {
fn len(&self) -> usize {
let (lower, upper) = self.size_hint();
// Note: This assertion is overly defensive, but it checks the invariant
// guaranteed by the trait. If this trait were rust-internal,
// we could use debug_assert!; assert_eq! will check all Rust user
// implementations too.
// guaranteed by the trait in all Rust user implementations too.
// If this trait were rust-internal, we could use debug_assert!, but
// any implementation for which it matters can override `len`.
assert_eq!(upper, Some(lower));
lower
}
Expand Down