Skip to content

Commit

Permalink
Auto merge of #137 - mbrubeck:extend, r=jdm
Browse files Browse the repository at this point in the history
Don't leak on panic in extend

This ensures that the length of the SmallVec is updated even if the iterator panics in `next`.

This uses `SetLenOnDrop` rather than setting the length inside the loop, because otherwise this suffers from the same optimization issue as rust-lang/rust#36355.

Fixes #136.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/137)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Jan 4, 2019
2 parents e8999ec + a9b8635 commit 7ac360c
Showing 1 changed file with 10 additions and 7 deletions.
17 changes: 10 additions & 7 deletions lib.rs
Expand Up @@ -1340,18 +1340,16 @@ impl<A: Array> Extend<A::Item> for SmallVec<A> {
self.reserve(lower_size_bound);

unsafe {
let len = self.len();
let ptr = self.as_mut_ptr().offset(len as isize);
let mut count = 0;
while count < lower_size_bound {
let (ptr, len_ptr, cap) = self.triple_mut();
let mut len = SetLenOnDrop::new(len_ptr);
while len.get() < cap {
if let Some(out) = iter.next() {
ptr::write(ptr.offset(count as isize), out);
count += 1;
ptr::write(ptr.offset(len.get() as isize), out);
len.increment_len(1);
} else {
break;
}
}
self.set_len(len + count);
}

for elem in iter {
Expand Down Expand Up @@ -1560,6 +1558,11 @@ impl<'a> SetLenOnDrop<'a> {
SetLenOnDrop { local_len: *len, len: len }
}

#[inline]
fn get(&self) -> usize {
self.local_len
}

#[inline]
fn increment_len(&mut self, increment: usize) {
self.local_len += increment;
Expand Down

0 comments on commit 7ac360c

Please sign in to comment.