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