Fix over-allocation in List::from_iter

This commit is contained in:
Brian Carroll 2022-07-20 08:34:16 +01:00
parent ba7b98bdaa
commit b14d9b5244
No known key found for this signature in database
GPG Key ID: 5C7B2EC4101703C0
2 changed files with 17 additions and 18 deletions

View File

@ -549,7 +549,7 @@ impl<T: Clone> FromIterator<T> for RocList<T> {
where
I: IntoIterator<Item = T>,
{
let mut iter = into.into_iter();
let iter = into.into_iter();
if std::mem::size_of::<T>() == 0 {
let count = iter.count();
@ -566,25 +566,23 @@ impl<T: Clone> FromIterator<T> for RocList<T> {
Self::with_capacity(init_capacity)
};
loop {
let start = list.length;
let elements = list.elements.unwrap().as_ptr();
for i in start..list.capacity {
if let Some(new_elem) = iter.next() {
unsafe {
elements
.add(i)
.write(ptr::read(&ManuallyDrop::new(new_elem)));
}
list.length += 1;
} else {
return list;
}
}
let mut elements = list.elements.unwrap().as_ptr();
for new_elem in iter {
// If the size_hint didn't give us a max, we may need to grow. 1.5x seems to be good, based on:
// https://archive.ph/Z2R8w and https://github.com/facebook/folly/blob/1f2706/folly/docs/FBVector.md
list.reserve(list.capacity / 2);
if list.length == list.capacity {
list.reserve(list.capacity / 2);
elements = list.elements.unwrap().as_ptr();
}
unsafe {
elements
.add(list.length)
.write(ptr::read(&ManuallyDrop::new(new_elem)));
}
list.length += 1;
}
list
}
}

View File

@ -162,6 +162,7 @@ mod test_roc_std {
let from_slice = RocList::from_slice(&elems);
let from_iter = RocList::from_iter(elems);
assert_eq!(from_iter, from_slice);
assert_eq!(from_iter.capacity(), from_slice.capacity());
}
#[test]