Question copy Vec<T>

For a type to be Copy, it must be valid to clone it by simply copying over the bytes it consists of. Be aware that the way a vector is laid out is like this:

+------------+
| The vector |
+------------+
      |
      V
+--------+--------+--------+-------------------------+
| Item 1 | Item 2 | Item 3 | Additional capacity...  |
+--------+--------+--------+-------------------------+

The important part is that the bytes that Copy is referring to is only the box I marked with “The vector”. The heap allocation that it has a pointer to is not part of this copy. The issue is that a vector has ownership of this heap allocation — you can't have two that point to the same, since this could cause all sorts of issues: What if one copy of the vector added an item and it ran out of capacity, so it had to reallocate the memory? Then the other vector would suddenly be looking at deallocated memory! Boom!

Of course, the vector is still Clone. This trait simply means that it can be cloned somehow. Of course this involves cloning every element in the vector, but it is possible.

As for how to solve your issue, the problem is that std::vec::IntoIter takes ownership of the vector. Of course, you could just clone the series before calling into_iter(), but a better solution is to borrow the collection instead:

impl Series {
    pub fn iter(&self) -> std::slice::Iter<Float> {
        self.data.iter()
    }
}

Although this is now an iterator over values of type &Float. Since Float is copy, you might want to copy them:

impl Series {
    pub fn iter(&self) -> std::iter::Copied<std::slice::Iter<Float>> {
        self.data.iter().copied()
    }
}
// or hide the exact kind of iterator...
impl Series {
    pub fn iter<'a>(&'a self) -> impl Iterator<Item = Float> + 'a {
        self.data.iter().copied()
    }
}

It's also common to implement IntoIterator for references to collections, e.g.

impl<'a> IntoIterator for &'a Series {
    type Item = Float;
    type IntoIter = std::iter::Copied<std::slice::Iter<'a, Float>>;
    
    fn into_iter(self) -> Self::IntoIter {
        self.data.iter().copied()
    }
}

This allows using &series in a for loop.

10 Likes