Not long enough error when iterating through a linked list

I am trying to create a linked list and an iterator to iterate over the list.

enum List<T> {
    Cons(T, Box<List<T>>),
    Nil,
}

struct ListIterator<'a, T:'a> {
    cur: &'a List<T>
}

impl<'a, T> Iterator<T> for ListIterator<'a, T> {
    fn next(&mut self) -> Option<T>{
        match self.cur {
            &Cons(val, next) => {self.cur = &*next; Some(val)},
            &Nil => None
        }
    }
}

      

But I am getting the following error:

error: `*next` does not live long enough

      

+3


source to share


1 answer


The error message indicates a real problem, but there is actually another one that the compiler should report instead, because it comes earlier. In the hand of the match

&Cons(val, next) => {self.cur = &*next; Some(val)},

      

you are trying to destroy a List object in &Cons(val,next)

which is an attempt to move val

and next

because of a borrowed pointer. It is forbidden. But if that were the case, val

and next

would have local variables with a fairly short lifetime. The error message you see is related to this: the following will be a local field that is about to be deleted. Therefore, the type &*next

is a reference with a lifetime parameter that refers to the lifetime of this local field. And it's too short to bring it back.

This requires the use of templates ref

and box

:

&Cons(ref val, box ref next) => { self.cur = next; Some(*val) },

      



Now val

is of type &T

and next

is of type &List

where both are references to your list data structure and nothing is moved. Note also that it Some(*val)

is required to T

be Copy

:

impl<'a, T: Copy> Iterator<T> for ListIterator<'a, T> {
...

      

But it Copy

is quite demanding. A more general way is to use Clone

like this:

impl<'a, T: Clone> Iterator<T> for ListIterator<'a, T> {
...
    &Cons(ref val, box ref next) => { self.cur = next; Some((*val).clone()) },

      

This works for more types. And if you don't want to clone the values, you can also do your own iterator &T

instead T

, as you do with vectors and slices.

+1


source







All Articles