diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 63828b482b9a9..91f9d8dda37b7 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -1720,7 +1720,12 @@ impl Iterator for IntoIterSorted { } #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] -impl ExactSizeIterator for IntoIterSorted {} +impl ExactSizeIterator for IntoIterSorted { + #[inline] + fn len(&self) -> usize { + self.inner.len() + } +} #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] impl FusedIterator for IntoIterSorted {} @@ -1846,7 +1851,12 @@ impl Iterator for DrainSorted<'_, T, A> { } #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl ExactSizeIterator for DrainSorted<'_, T, A> {} +impl ExactSizeIterator for DrainSorted<'_, T, A> { + #[inline] + fn len(&self) -> usize { + self.inner.len() + } +} #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] impl FusedIterator for DrainSorted<'_, T, A> {} diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 8bc0e08a4b26b..62acabd48ee90 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1244,7 +1244,11 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Iter<'_, T> {} +impl ExactSizeIterator for Iter<'_, T> { + fn len(&self) -> usize { + self.len + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Iter<'_, T> {} @@ -1312,7 +1316,11 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IterMut<'_, T> {} +impl ExactSizeIterator for IterMut<'_, T> { + fn len(&self) -> usize { + self.len + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IterMut<'_, T> {} @@ -2023,7 +2031,11 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.list.len + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 321621d18be9f..c41925fd6e57e 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -268,7 +268,11 @@ impl DoubleEndedIterator for Drain<'_, T, A> { } #[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T, A> {} +impl ExactSizeIterator for Drain<'_, T, A> { + fn len(&self) -> usize { + self.remaining + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Drain<'_, T, A> {} diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index 8705a9c3d2679..96b09203dbe92 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -241,6 +241,10 @@ impl Drop for Drain<'_, T, A> { #[stable(feature = "drain", since = "1.6.0")] impl ExactSizeIterator for Drain<'_, T, A> { + fn len(&self) -> usize { + self.iter.len() + } + fn is_empty(&self) -> bool { self.iter.is_empty() } diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index d571e35828aeb..7d62ac61db128 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -48,7 +48,11 @@ impl DoubleEndedIterator for Splice<'_, I, A> { } #[stable(feature = "vec_splice", since = "1.21.0")] -impl ExactSizeIterator for Splice<'_, I, A> {} +impl ExactSizeIterator for Splice<'_, I, A> { + fn len(&self) -> usize { + self.drain.len() + } +} #[stable(feature = "vec_splice", since = "1.21.0")] impl Drop for Splice<'_, I, A> { diff --git a/library/core/src/iter/adapters/map_windows.rs b/library/core/src/iter/adapters/map_windows.rs index 0dada9eb6aacf..e090fdfc97dee 100644 --- a/library/core/src/iter/adapters/map_windows.rs +++ b/library/core/src/iter/adapters/map_windows.rs @@ -97,13 +97,30 @@ impl MapWindowsInner { (lo, hi) } else { // If the first `N` items are not yet yielded by the inner iterator, - // the first `N` elements should be counted as one window, so both bounds - // should subtract `N - 1`. + // the first `N` elements should be counted as one window, so `N - 1` should + // subtracted from both bounds. (lo.saturating_sub(N - 1), hi.map(|hi| hi.saturating_sub(N - 1))) } } } +impl MapWindowsInner { + fn len(&self) -> usize { + let Some(ref iter) = self.iter else { return 0 }; + let n = iter.len(); + if self.buffer.is_some() { + // If the first `N` items are already yielded by the inner iterator, + // the length is then equal to the that of the inner iterator's. + n + } else { + // If the first `N` items are not yet yielded by the inner iterator, + // the first `N` elements should be counted as one window, so `N - 1` should + // be subtracted from the length. + n.saturating_sub(N - 1) + } + } +} + impl Buffer { fn try_from_iter(iter: &mut impl Iterator) -> Option { let first_half = crate::array::iter_next_chunk(iter).ok()?; @@ -269,6 +286,9 @@ where I: ExactSizeIterator, F: FnMut(&[I::Item; N]) -> R, { + fn len(&self) -> usize { + self.inner.len() + } } #[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")] diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index a55de75d56c6e..dfb32ba8f794f 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -168,7 +168,13 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Peekable {} +impl ExactSizeIterator for Peekable { + #[inline] + fn len(&self) -> usize { + let peek_len = usize::from(matches!(self.peeked, Some(Some(_)))); + self.iter.len().saturating_add(peek_len) + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Peekable {} diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index 55c4a7f14fbd6..9f550a4d56d02 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -185,7 +185,14 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Skip where I: ExactSizeIterator {} +impl ExactSizeIterator for Skip +where + I: ExactSizeIterator, +{ + fn len(&self) -> usize { + self.iter.len().saturating_sub(self.n) + } +} #[stable(feature = "double_ended_skip_iterator", since = "1.9.0")] impl DoubleEndedIterator for Skip diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index b96335f415257..fb602204f3dcd 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -238,7 +238,14 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Take where I: ExactSizeIterator {} +impl ExactSizeIterator for Take +where + I: ExactSizeIterator, +{ + fn len(&self) -> usize { + cmp::min(self.n, self.iter.len()) + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Take where I: FusedIterator {} diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 57098b95f641b..6138997bf51be 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -807,7 +807,7 @@ impl Option { } #[inline] - const fn len(&self) -> usize { + pub(crate) const fn len(&self) -> usize { // Using the intrinsic avoids emitting a branch to get the 0 or 1. let discriminant: isize = crate::intrinsics::discriminant_value(self); discriminant as usize @@ -2461,6 +2461,7 @@ impl<'a, A> Iterator for Iter<'a, A> { fn next(&mut self) -> Option<&'a A> { self.inner.next() } + #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() @@ -2476,7 +2477,11 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Iter<'_, A> {} +impl ExactSizeIterator for Iter<'_, A> { + fn len(&self) -> usize { + self.inner.len() + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Iter<'_, A> {} @@ -2511,6 +2516,7 @@ impl<'a, A> Iterator for IterMut<'a, A> { fn next(&mut self) -> Option<&'a mut A> { self.inner.next() } + #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() @@ -2526,7 +2532,11 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IterMut<'_, A> {} +impl ExactSizeIterator for IterMut<'_, A> { + fn len(&self) -> usize { + self.inner.len() + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IterMut<'_, A> {} @@ -2552,6 +2562,7 @@ impl Iterator for IntoIter { fn next(&mut self) -> Option { self.inner.next() } + #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() @@ -2567,7 +2578,11 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.inner.len() + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 9afa71ec0f117..27838118c45b2 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1984,9 +1984,10 @@ impl<'a, T> Iterator for Iter<'a, T> { fn next(&mut self) -> Option<&'a T> { self.inner.take() } + #[inline] fn size_hint(&self) -> (usize, Option) { - let n = if self.inner.is_some() { 1 } else { 0 }; + let n = self.len(); (n, Some(n)) } } @@ -2000,7 +2001,11 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Iter<'_, T> {} +impl ExactSizeIterator for Iter<'_, T> { + fn len(&self) -> usize { + self.inner.len() + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Iter<'_, T> {} @@ -2035,7 +2040,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { } #[inline] fn size_hint(&self) -> (usize, Option) { - let n = if self.inner.is_some() { 1 } else { 0 }; + let n = self.len(); (n, Some(n)) } } @@ -2049,7 +2054,11 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IterMut<'_, T> {} +impl ExactSizeIterator for IterMut<'_, T> { + fn len(&self) -> usize { + self.inner.len() + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IterMut<'_, T> {} @@ -2079,9 +2088,10 @@ impl Iterator for IntoIter { fn next(&mut self) -> Option { self.inner.take() } + #[inline] fn size_hint(&self) -> (usize, Option) { - let n = if self.inner.is_some() { 1 } else { 0 }; + let n = self.len(); (n, Some(n)) } } @@ -2095,7 +2105,11 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.inner.len() + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index a2fbf6ead6461..83232c6a56bef 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1365,12 +1365,8 @@ impl<'a, T> Iterator for Windows<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - if self.size.get() > self.v.len() { - (0, Some(0)) - } else { - let size = self.v.len() - self.size.get() + 1; - (size, Some(size)) - } + let n = self.len(); + (n, Some(n)) } #[inline] @@ -1440,7 +1436,17 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Windows<'_, T> {} +impl ExactSizeIterator for Windows<'_, T> { + #[inline] + fn len(&self) -> usize { + if self.size.get() > self.v.len() { 0 } else { self.v.len() - self.size.get() + 1 } + } + + #[inline] + fn is_empty(&self) -> bool { + self.size.get() > self.v.len() + } +} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Windows<'_, T> {} @@ -1520,14 +1526,8 @@ impl<'a, T> Iterator for Chunks<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - if self.v.is_empty() { - (0, Some(0)) - } else { - let n = self.v.len() / self.chunk_size; - let rem = self.v.len() % self.chunk_size; - let n = if rem > 0 { n + 1 } else { n }; - (n, Some(n)) - } + let n = self.len(); + (n, Some(n)) } #[inline] @@ -1625,7 +1625,17 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Chunks<'_, T> {} +impl ExactSizeIterator for Chunks<'_, T> { + #[inline] + fn len(&self) -> usize { + if self.v.is_empty() { 0 } else { self.v.len().div_ceil(self.chunk_size) } + } + + #[inline] + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Chunks<'_, T> {} @@ -1702,14 +1712,8 @@ impl<'a, T> Iterator for ChunksMut<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - if self.v.is_empty() { - (0, Some(0)) - } else { - let n = self.v.len() / self.chunk_size; - let rem = self.v.len() % self.chunk_size; - let n = if rem > 0 { n + 1 } else { n }; - (n, Some(n)) - } + let n = self.len(); + (n, Some(n)) } #[inline] @@ -1806,7 +1810,17 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for ChunksMut<'_, T> {} +impl ExactSizeIterator for ChunksMut<'_, T> { + #[inline] + fn len(&self) -> usize { + if self.v.is_empty() { 0 } else { self.v.len().div_ceil(self.chunk_size) } + } + + #[inline] + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for ChunksMut<'_, T> {} @@ -1920,7 +1934,7 @@ impl<'a, T> Iterator for ChunksExact<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - let n = self.v.len() / self.chunk_size; + let n = self.len(); (n, Some(n)) } @@ -1985,6 +1999,12 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> { #[stable(feature = "chunks_exact", since = "1.31.0")] impl ExactSizeIterator for ChunksExact<'_, T> { + #[inline] + fn len(&self) -> usize { + self.v.len() / self.chunk_size + } + + #[inline] fn is_empty(&self) -> bool { self.v.is_empty() } @@ -2080,7 +2100,7 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - let n = self.v.len() / self.chunk_size; + let n = self.len(); (n, Some(n)) } @@ -2152,6 +2172,12 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> { #[stable(feature = "chunks_exact", since = "1.31.0")] impl ExactSizeIterator for ChunksExactMut<'_, T> { + #[inline] + fn len(&self) -> usize { + self.v.len() / self.chunk_size + } + + #[inline] fn is_empty(&self) -> bool { self.v.is_empty() } @@ -2228,8 +2254,8 @@ impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { #[inline] fn size_hint(&self) -> (usize, Option) { - let size = self.v.len().saturating_sub(N - 1); - (size, Some(size)) + let n = self.len(); + (n, Some(n)) } #[inline] @@ -2271,6 +2297,12 @@ impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> { #[unstable(feature = "array_windows", issue = "75027")] impl ExactSizeIterator for ArrayWindows<'_, T, N> { + #[inline] + fn len(&self) -> usize { + self.v.len().saturating_sub(N - 1) + } + + #[inline] fn is_empty(&self) -> bool { self.v.len() < N } @@ -2344,14 +2376,8 @@ impl<'a, T> Iterator for RChunks<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - if self.v.is_empty() { - (0, Some(0)) - } else { - let n = self.v.len() / self.chunk_size; - let rem = self.v.len() % self.chunk_size; - let n = if rem > 0 { n + 1 } else { n }; - (n, Some(n)) - } + let n = self.len(); + (n, Some(n)) } #[inline] @@ -2435,7 +2461,17 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { } #[stable(feature = "rchunks", since = "1.31.0")] -impl ExactSizeIterator for RChunks<'_, T> {} +impl ExactSizeIterator for RChunks<'_, T> { + #[inline] + fn len(&self) -> usize { + if self.v.is_empty() { 0 } else { self.v.len().div_ceil(self.chunk_size) } + } + + #[inline] + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RChunks<'_, T> {} @@ -2517,14 +2553,8 @@ impl<'a, T> Iterator for RChunksMut<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - if self.v.is_empty() { - (0, Some(0)) - } else { - let n = self.v.len() / self.chunk_size; - let rem = self.v.len() % self.chunk_size; - let n = if rem > 0 { n + 1 } else { n }; - (n, Some(n)) - } + let n = self.len(); + (n, Some(n)) } #[inline] @@ -2621,7 +2651,17 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> { } #[stable(feature = "rchunks", since = "1.31.0")] -impl ExactSizeIterator for RChunksMut<'_, T> {} +impl ExactSizeIterator for RChunksMut<'_, T> { + #[inline] + fn len(&self) -> usize { + if self.v.is_empty() { 0 } else { self.v.len().div_ceil(self.chunk_size) } + } + + #[inline] + fn is_empty(&self) -> bool { + self.v.is_empty() + } +} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RChunksMut<'_, T> {} @@ -2735,7 +2775,7 @@ impl<'a, T> Iterator for RChunksExact<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - let n = self.v.len() / self.chunk_size; + let n = self.len(); (n, Some(n)) } @@ -2804,6 +2844,12 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { #[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> ExactSizeIterator for RChunksExact<'a, T> { + #[inline] + fn len(&self) -> usize { + self.v.len() / self.chunk_size + } + + #[inline] fn is_empty(&self) -> bool { self.v.is_empty() } @@ -2899,7 +2945,7 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - let n = self.v.len() / self.chunk_size; + let n = self.len(); (n, Some(n)) } @@ -2976,6 +3022,12 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> { #[stable(feature = "rchunks", since = "1.31.0")] impl ExactSizeIterator for RChunksExactMut<'_, T> { + #[inline] + fn len(&self) -> usize { + self.v.len() / self.chunk_size + } + + #[inline] fn is_empty(&self) -> bool { self.v.is_empty() }