Skip to content

Commit

Permalink
Don't leak on panic in extend
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mbrubeck committed Jan 4, 2019
1 parent d6bfa84 commit a9b8635
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 a9b8635

Please sign in to comment.