remove IntoIter for RocList

This implies we get ownership of the data inside the iterator, but that's
not true--it's not safe to change values in place because Roc might still
hold a reference to the memory.
This commit is contained in:
Brian Hicks 2022-09-07 14:59:29 -05:00
parent 0b78e14978
commit 2a141395d9
No known key found for this signature in database
GPG Key ID: C4F324B9CAAB0D50

View File

@ -501,62 +501,6 @@ impl<T, const SIZE: usize> From<[T; SIZE]> for RocList<T> {
}
}
impl<'a, T> IntoIterator for &'a RocList<T> {
type Item = &'a T;
type IntoIter = core::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<T> IntoIterator for RocList<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter { list: self, idx: 0 }
}
}
pub struct IntoIter<T> {
list: RocList<T>,
idx: usize,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.list.len() <= self.idx {
return None;
}
let elements = self.list.elements?;
let element_ptr = unsafe { elements.as_ptr().add(self.idx) };
self.idx += 1;
// Return the element.
Some(unsafe { ManuallyDrop::into_inner(element_ptr.read()) })
}
}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
// If there are any elements left that need to be dropped, drop them.
if let Some(elements) = self.list.elements {
// Set the list's length to zero to prevent double-frees.
// Note that this leaks if dropping any of the elements panics.
let len = mem::take(&mut self.list.length);
// Drop the elements that haven't been returned from the iterator.
for i in self.idx..len {
mem::drop::<T>(unsafe { ManuallyDrop::take(&mut *elements.as_ptr().add(i)) })
}
}
}
}
impl<T: Hash> Hash for RocList<T> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
// This is the same as Rust's Vec implementation, which