Rollup merge of #62316 - khuey:efficient_last, r=sfackler
When possible without changing semantics, implement Iterator::last in terms of DoubleEndedIterator::next_back for types in liballoc and libcore. Provided that the iterator has finite length and does not trigger user-provided code, this is safe. What follows is a full list of the DoubleEndedIterators in liballoc/libcore and whether this optimization is safe, and if not, why not. src/liballoc/boxed.rs Box: Pass through to avoid defeating optimization of the underlying DoubleIterator implementation. This has no correctness impact. src/liballoc/collections/binary_heap.rs Iter: Pass through to avoid defeating optimizations on slice::Iter IntoIter: Not safe, changes Drop order Drain: Not safe, changes Drop order src/liballoc/collections/btree/map.rs Iter: Safe to call next_back, invokes no user defined code. IterMut: ditto IntoIter: Not safe, changes Drop order Keys: Safe to call next_back, invokes no user defined code. Values: ditto ValuesMut: ditto Range: ditto RangeMut: ditto src/liballoc/collections/btree/set.rs Iter: Safe to call next_back, invokes no user defined code. IntoIter: Not safe, changes Drop order Range: Safe to call next_back, invokes no user defined code. src/liballoc/collections/linked_list.rs Iter: Safe to call next_back, invokes no user defined code. IterMut: ditto IntoIter: Not safe, changes Drop order src/liballoc/collections/vec_deque.rs Iter: Safe to call next_back, invokes no user defined code. IterMut: ditto IntoIter: Not safe, changes Drop order Drain: ditto src/liballoc/string.rs Drain: Safe because return type is a primitive (char) src/liballoc/vec.rs IntoIter: Not safe, changes Drop order Drain: ditto Splice: ditto src/libcore/ascii.rs EscapeDefault: Safe because return type is a primitive (u8) src/libcore/iter/adapters/chain.rs Chain: Not safe, invokes user defined code (Iterator impl) src/libcore/iter/adapters/flatten.rs FlatMap: Not safe, invokes user defined code (Iterator impl) Flatten: ditto FlattenCompat: ditto src/libcore/iter/adapters/mod.rs Rev: Not safe, invokes user defined code (Iterator impl) Copied: ditto Cloned: Not safe, invokes user defined code (Iterator impl and T::clone) Map: Not safe, invokes user defined code (Iterator impl + closure) Filter: ditto FilterMap: ditto Enumerate: Not safe, invokes user defined code (Iterator impl) Skip: ditto Fuse: ditto Inspect: ditto src/libcore/iter/adapters/zip.rs Zip: Not safe, invokes user defined code (Iterator impl) src/libcore/iter/range.rs ops::Range: Not safe, changes Drop order, but ALREADY HAS SPECIALIZATION ops::RangeInclusive: ditto src/libcore/iter/sources.rs Repeat: Not safe, calling last should iloop. Empty: No point, iterator is at most one item long. Once: ditto OnceWith: ditto src/libcore/option.rs Item: No point, iterator is at most one item long. Iter: ditto IterMut: ditto IntoIter: ditto src/libcore/result.rs Iter: No point, iterator is at most one item long IterMut: ditto IntoIter: ditto src/libcore/slice/mod.rs Split: Not safe, invokes user defined closure SplitMut: ditto RSplit: ditto RSplitMut: ditto Windows: Safe, already has specialization Chunks: ditto ChunksMut: ditto ChunksExact: ditto ChunksExactMut: ditto RChunks: ditto RChunksMut: ditto RChunksExact: ditto RChunksExactMut: ditto src/libcore/str/mod.rs Chars: Safe, already has specialization CharIndices: ditto Bytes: ditto Lines: Safe to call next_back, invokes no user defined code. LinesAny: Deprecated Everything that is generic over P: Pattern: Not safe because Pattern invokes user defined code. SplitWhitespace: Safe to call next_back, invokes no user defined code. SplitAsciiWhitespace: ditto This is attempt 2 of #60130. r? @sfackler
This commit is contained in:
commit
4049a3cf1b
|
@ -728,6 +728,14 @@ impl<I: Iterator + ?Sized> Iterator for Box<I> {
|
||||||
(**self).nth(n)
|
(**self).nth(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<I: Iterator + Sized> Iterator for Box<I> {
|
||||||
|
fn last(self) -> Option<I::Item> where I: Sized {
|
||||||
|
(*self).last()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
|
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
|
||||||
fn next_back(&mut self) -> Option<I::Item> {
|
fn next_back(&mut self) -> Option<I::Item> {
|
||||||
|
|
|
@ -1035,6 +1035,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.iter.size_hint()
|
self.iter.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(self) -> Option<&'a T> {
|
||||||
|
self.iter.last()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -1193,6 +1193,10 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
(self.length, Some(self.length))
|
(self.length, Some(self.length))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<(&'a K, &'a V)> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "fused", since = "1.26.0")]
|
#[stable(feature = "fused", since = "1.26.0")]
|
||||||
|
@ -1253,6 +1257,10 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
(self.length, Some(self.length))
|
(self.length, Some(self.length))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<(&'a K, &'a mut V)> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -1421,6 +1429,10 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.inner.size_hint()
|
self.inner.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<&'a K> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -1458,6 +1470,10 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.inner.size_hint()
|
self.inner.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<&'a V> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -1495,6 +1511,10 @@ impl<'a, K, V> Iterator for Range<'a, K, V> {
|
||||||
unsafe { Some(self.next_unchecked()) }
|
unsafe { Some(self.next_unchecked()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<(&'a K, &'a V)> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "map_values_mut", since = "1.10.0")]
|
#[stable(feature = "map_values_mut", since = "1.10.0")]
|
||||||
|
@ -1508,6 +1528,10 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.inner.size_hint()
|
self.inner.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<&'a mut V> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "map_values_mut", since = "1.10.0")]
|
#[stable(feature = "map_values_mut", since = "1.10.0")]
|
||||||
|
@ -1626,6 +1650,10 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> {
|
||||||
unsafe { Some(self.next_unchecked()) }
|
unsafe { Some(self.next_unchecked()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<(&'a K, &'a mut V)> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V> RangeMut<'a, K, V> {
|
impl<'a, K, V> RangeMut<'a, K, V> {
|
||||||
|
|
|
@ -1019,6 +1019,9 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.iter.size_hint()
|
self.iter.size_hint()
|
||||||
}
|
}
|
||||||
|
fn last(mut self) -> Option<&'a T> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
||||||
|
@ -1073,6 +1076,10 @@ impl<'a, T> Iterator for Range<'a, T> {
|
||||||
fn next(&mut self) -> Option<&'a T> {
|
fn next(&mut self) -> Option<&'a T> {
|
||||||
self.iter.next().map(|(k, _)| k)
|
self.iter.next().map(|(k, _)| k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<&'a T> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "btree_range", since = "1.17.0")]
|
#[stable(feature = "btree_range", since = "1.17.0")]
|
||||||
|
|
|
@ -832,6 +832,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
(self.len, Some(self.len))
|
(self.len, Some(self.len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<&'a T> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -881,6 +886,11 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
(self.len, Some(self.len))
|
(self.len, Some(self.len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<&'a mut T> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -2206,6 +2206,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||||
self.tail = self.head - iter.len();
|
self.tail = self.head - iter.len();
|
||||||
final_res
|
final_res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<&'a T> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -2319,6 +2324,11 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
||||||
accum = front.iter_mut().fold(accum, &mut f);
|
accum = front.iter_mut().fold(accum, &mut f);
|
||||||
back.iter_mut().fold(accum, &mut f)
|
back.iter_mut().fold(accum, &mut f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<&'a mut T> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -2385,6 +2385,11 @@ impl Iterator for Drain<'_> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.iter.size_hint()
|
self.iter.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<char> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "drain", since = "1.6.0")]
|
#[stable(feature = "drain", since = "1.6.0")]
|
||||||
|
|
|
@ -117,6 +117,7 @@ impl Iterator for EscapeDefault {
|
||||||
type Item = u8;
|
type Item = u8;
|
||||||
fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
|
fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
|
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
|
||||||
|
fn last(mut self) -> Option<u8> { self.next_back() }
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl DoubleEndedIterator for EscapeDefault {
|
impl DoubleEndedIterator for EscapeDefault {
|
||||||
|
|
|
@ -1333,6 +1333,11 @@ impl<'a> Iterator for Lines<'a> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.0.size_hint()
|
self.0.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<&'a str> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -4241,6 +4246,11 @@ impl<'a> Iterator for SplitWhitespace<'a> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.inner.size_hint()
|
self.inner.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<&'a str> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "split_whitespace", since = "1.1.0")]
|
#[stable(feature = "split_whitespace", since = "1.1.0")]
|
||||||
|
@ -4267,6 +4277,11 @@ impl<'a> Iterator for SplitAsciiWhitespace<'a> {
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.inner.size_hint()
|
self.inner.size_hint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<&'a str> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
|
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
|
||||||
|
|
Loading…
Reference in New Issue