Skip to content

Commit 3cfa3aa

Browse files
author
Markus Westerlind
committed
Use try_fold in Vec::extend
Should put less stress on LLVM since there are less closures passed around and lets us refine how much we reserve with `size_hint` if the first guess is too low.
1 parent ddabd76 commit 3cfa3aa

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

src/liballoc/vec.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,8 +1559,8 @@ impl<T: Default> Vec<T> {
15591559
#[unstable(feature = "vec_resize_default", issue = "41758")]
15601560
#[rustc_deprecated(
15611561
reason = "This is moving towards being removed in favor \
1562-
of `.resize_with(Default::default)`. If you disagree, please comment \
1563-
in the tracking issue.",
1562+
of `.resize_with(Default::default)`. If you disagree, please comment \
1563+
in the tracking issue.",
15641564
since = "1.33.0"
15651565
)]
15661566
pub fn resize_default(&mut self, new_len: usize) {
@@ -2122,7 +2122,7 @@ where
21222122
}
21232123

21242124
impl<T> Vec<T> {
2125-
fn extend_desugared<I: Iterator<Item = T>>(&mut self, iterator: I) {
2125+
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
21262126
// This is the case for a general iterator.
21272127
//
21282128
// This function should be the moral equivalent of:
@@ -2132,8 +2132,34 @@ impl<T> Vec<T> {
21322132
// }
21332133
let (lower, _) = iterator.size_hint();
21342134
self.reserve(lower);
2135-
2136-
iterator.for_each(|element| self.push(element));
2135+
loop {
2136+
let cap = self.capacity();
2137+
let result = iterator.by_ref().try_fold((), |(), element| {
2138+
let len = self.len();
2139+
if len == cap {
2140+
Err(element)
2141+
} else {
2142+
unsafe {
2143+
ptr::write(self.get_unchecked_mut(len), element);
2144+
self.set_len(len + 1);
2145+
Ok(())
2146+
}
2147+
}
2148+
});
2149+
match result {
2150+
Ok(()) => return,
2151+
Err(element) => {
2152+
let (lower, _) = iterator.size_hint();
2153+
self.reserve(lower.saturating_add(1));
2154+
unsafe {
2155+
let len = self.len();
2156+
ptr::write(self.get_unchecked_mut(len), element);
2157+
// NB can't overflow since we would have had to alloc the address space
2158+
self.set_len(len + 1);
2159+
}
2160+
}
2161+
}
2162+
}
21372163
}
21382164

21392165
/// Creates a splicing iterator that replaces the specified range in the vector

0 commit comments

Comments
 (0)