0

I read a bunch of seemingly duplicate questions but either didn't know how to use that to resolve my issue or the suggested answers didn't seem to work.

I am trying to implement a custom, cursor like iterator for a skip list. I am getting the following error and have pulled out all my hair and nails trying to resolve it:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/memtable.rs:87:40
   |
87 |         self.current_node = self.store.find_greater_or_equal_node(target);
   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 86:13...
  --> src/memtable.rs:86:13
   |
86 |     fn seek(&mut self, target: &Self::Key) -> Result<(), Self::Error> {
   |             ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/memtable.rs:87:29
   |
87 |         self.current_node = self.store.find_greater_or_equal_node(target);
   |                             ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 78:6...
  --> src/memtable.rs:78:6
   |
78 | impl<'a> DbIterator<'a> for SkipListMemTableIter<'a> {
   |      ^^
note: ...so that the expression is assignable
  --> src/memtable.rs:87:29
   |
87 |         self.current_node = self.store.find_greater_or_equal_node(target);
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `Option<&'a SkipNode<InternalKey, Vec<u8>>>`
              found `Option<&SkipNode<InternalKey, Vec<u8>>>`

The code is:

use nerdondon_hopscotch::concurrent_skiplist::{ConcurrentSkipList, SkipNode};

impl SkipListMemTable {
    fn iter(&self) -> Box<dyn DbIterator<Key = InternalKey, Error = DbError> + '_> {
        Box::new(SkipListMemTableIter {
            store: Arc::clone(&self.store),
            current_node: self.store.first_node(),
        })
    }
}

struct SkipListMemTableIter<'a> {
    store: Arc<ConcurrentSkipList<InternalKey, Vec<u8>>>,

    current_node: Option<&'a SkipNode<InternalKey, Vec<u8>>>,
}

impl<'a> DbIterator<'a> for SkipListMemTableIter<'a> {
    type Key = InternalKey;
    type Error = DbError;

    fn seek(&mut self, target: &Self::Key) -> Result<(), Self::Error> {
        self.current_node = self.store.find_greater_or_equal_node(target);

        Ok(())
    }
}

/// Iterator trait
pub trait DbIterator<'i>
{
    type Key;
    type Error;

    fn seek(&mut self, target: &Self::Key) -> Result<(), Self::Error>;

    // also tried but this isn't what i want since it make it borrow for the lifetime of the iterator
    // but i need to be able to call other methods on the iterator
    // fn seek(&'i mut self, target: &Self::Key) -> Result<(), Self::Error>;

    fn next(&mut self) -> Option<(&Self::Key, &Vec<u8>)>;
}

I have tried various kind of lifetime annotations, one of which i commented on above. I'm confused at what exactly is wrong. I have an Arc of the backing collection so it seems that the reference in self.current_node should live just fine. Is that true? If so i'm not sure how to tell Rust.

cross-posted on the rust user forum - https://users.rust-lang.org/t/cannot-infer-appropriate-lifetime-with-custom-iterator-trait/70091

nerdondon
  • 26
  • 1
  • 3

0 Answers0