Skip to content

Commit a9b8635

Browse files
committed
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.
1 parent d6bfa84 commit a9b8635

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

lib.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -1340,18 +1340,16 @@ impl<A: Array> Extend<A::Item> for SmallVec<A> {
13401340
self.reserve(lower_size_bound);
13411341

13421342
unsafe {
1343-
let len = self.len();
1344-
let ptr = self.as_mut_ptr().offset(len as isize);
1345-
let mut count = 0;
1346-
while count < lower_size_bound {
1343+
let (ptr, len_ptr, cap) = self.triple_mut();
1344+
let mut len = SetLenOnDrop::new(len_ptr);
1345+
while len.get() < cap {
13471346
if let Some(out) = iter.next() {
1348-
ptr::write(ptr.offset(count as isize), out);
1349-
count += 1;
1347+
ptr::write(ptr.offset(len.get() as isize), out);
1348+
len.increment_len(1);
13501349
} else {
13511350
break;
13521351
}
13531352
}
1354-
self.set_len(len + count);
13551353
}
13561354

13571355
for elem in iter {
@@ -1560,6 +1558,11 @@ impl<'a> SetLenOnDrop<'a> {
15601558
SetLenOnDrop { local_len: *len, len: len }
15611559
}
15621560

1561+
#[inline]
1562+
fn get(&self) -> usize {
1563+
self.local_len
1564+
}
1565+
15631566
#[inline]
15641567
fn increment_len(&mut self, increment: usize) {
15651568
self.local_len += increment;

0 commit comments

Comments
 (0)