Skip to content

Commit b1e9e39

Browse files
Use internal iteration in Vec::extend_desugared()
Because LLVM is unable to optimize well external iteration with some iterator kinds (e.g. `chain()`). To do that I had to hoist the `size_hint()` call to the beginning of the loop (since I no longer have access to the iterator inside the loop), which might slightly pessimize certain iterators that are able to give more accurate size bounds during iteration (e.g. `flatten()`). However, the effect should not be big, and also, common iterators like these also suffer from the external iteration optimizibility problem (e.g. `flatten()`).
1 parent a1208bf commit b1e9e39

File tree

1 file changed

+6
-5
lines changed

1 file changed

+6
-5
lines changed

library/alloc/src/vec/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3780,19 +3780,20 @@ impl<T, A: Allocator> Vec<T, A> {
37803780
// they have no further optimizations to apply
37813781
#[cfg(not(no_global_oom_handling))]
37823782
#[track_caller]
3783-
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
3783+
fn extend_desugared<I: Iterator<Item = T>>(&mut self, iterator: I) {
37843784
// This is the case for a general iterator.
37853785
//
37863786
// This function should be the moral equivalent of:
37873787
//
37883788
// for item in iterator {
37893789
// self.push(item);
37903790
// }
3791-
while let Some(element) = iterator.next() {
3791+
let (lower, _) = iterator.size_hint();
3792+
let initial_len = self.len();
3793+
iterator.for_each(move |element| {
37923794
let len = self.len();
37933795
if len == self.capacity() {
3794-
let (lower, _) = iterator.size_hint();
3795-
self.reserve(lower.saturating_add(1));
3796+
self.reserve(lower.saturating_sub(len - initial_len).saturating_add(1));
37963797
}
37973798
unsafe {
37983799
ptr::write(self.as_mut_ptr().add(len), element);
@@ -3801,7 +3802,7 @@ impl<T, A: Allocator> Vec<T, A> {
38013802
// NB can't overflow since we would have had to alloc the address space
38023803
self.set_len(len + 1);
38033804
}
3804-
}
3805+
});
38053806
}
38063807

38073808
// specific extend for `TrustedLen` iterators, called both by the specializations

0 commit comments

Comments
 (0)