'Trouble implementing custom IntoIterator trait

I'm new to rust, so forgive me if the question is naive.

I'm trying to build an OS in rust and I'm following this tutorial. The OS doesn't have memory management yet, so the goal is to build an object which is like a vector in that it can be pushed and popped etc, but it lives on the stack. We do this by initializing it with an array of fixed size. It looks like this:

#[derive(Debug)]
pub struct StackVec<'a, T: 'a> {
    storage: &'a mut [T],
    len: usize
}

impl<'a, T: 'a> StackVec<'a, T> {

    pub fn new(storage: &'a mut [T]) -> StackVec<'a, T> {
        StackVec {
            storage: storage,
            len: 0,
        }
    }

    pub fn with_len(storage: &'a mut [T], len: usize) -> StackVec<'a, T> {
        if len > storage.len(){
            panic!();
        }

        StackVec{
            storage: storage,
            len: len
        }
    }

    pub fn capacity(&self) -> usize {
        self.storage.len()
    }

    pub fn into_slice(self) -> &'a mut [T] {
        &mut self.storage[0..self.len]
    }
  
    // Other functions which aren't relevant for the question.

}

Popping and pushing increases and decreases the len variable and adds and removes entries from the appropriate place in the array.

Now, we also need to implement the IntoIterator trait. Given that the StackVec contains a reference to an array, I thought that I could just return an iterator from the underlying array:

impl <'a, T:'a> IntoIterator for StackVec<'a, T> {
    type Item = T;
    type IntoIter = core::array::IntoIter; // <- Throws "not found in `core::array"

    fn into_iter(self) -> Self::IntoIter {
        self.into_slice().into_iter()
    }
}

But no matter how much I play around with it, it still doesn't want to compile. I can't find a way to express using types that into_itershould return the iterator for the array. What am I doing wrong?



Solution 1:[1]

Different problems here:

  • You cannot use array::IntoIterator because you do not have an array, you have a slice, which is quite different. It can be solved, for example, by using the proper core::slice::Iter as in the example.
  • You are trying to return T but in reality you only give access to &T, so return Item should be &T
  • Your into_slice method uses a &mut which is not necessary, you can reslice the storage for this implementation.
impl <'a, T:'a> IntoIterator for StackVec<'a, T> {
    type Item = &'a T;
    type IntoIter = core::slice::Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.storage[0..self.len].into_iter()
    }
}

Playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1