Lifetime of Vec element in hierarchical Iterator

I have some types. (The Send type here is a customized type instead of std::marker::Send)

pub struct Par { /* ... */ }
pub struct Send {
    pub data: Vec<Par>,
    // ...
}

They implement the same trait

pub trait Sortable<ITER> where ITER : Iterator<Item = Node> {
    fn score_tree_iter(self) -> ITER;
}

impl<'a> Sortable<ParScoreTreeIter<'a>> for &'a Par {
    fn score_tree_iter(self) -> ParScoreTreeIter<'a> {
        ParScoreTreeIter{
            term : self,
            stage : 0,
        }
    }
}

struct ParScoreTreeIter<'a> {
    term : &'a Par,
    stage : u16,
}

impl<'a> Sortable<SendScoreTreeIter<'a>> for &'a Send {
    fn score_tree_iter(self) -> SendScoreTreeIter<'a> {
        SendScoreTreeIter{
            term : self,
            stage : 0,
            data : &self.data[..],
        }
    }
}

struct SendScoreTreeIter<'a> {
    term : &'a Send,
    stage : u16,
    data : &'a [Par],
}

The idea is to create a hierarchical iterator, when it found a nested type, return the iterator of the nested type.

This line(rholang-rust/sort_send.rs at sort · wangjia184/rholang-rust · GitHub) fails with error

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
   --> model/src/sort/sort_send.rs:107:28
    |
107 |             let sub_iter = self.data[0].score_tree_iter();

The problem is from Vec<Par>. Really dont know how to solve this error.

May someone help? thank you in advance

The full source code is here: https://github.com/wangjia184/rholang-rust/blob/sort/model/src/sort/

Can you post the full error?

Trait objects like dyn Iterator have a default lifetime which is often 'static. If you don't want it to be 'static, you'll need some sort of lifetime parameter on your Node, like

enum Node<'a> {
    // You may even want two lifetimes...
    Children(Box<dyn Iterator<Item = Node<'a>> + 'a>),
    // [other variants]
}

This lifetime parameter will need to show up wherever you use Node in a place were elision doesn't work (and you may want to use it in some of those cases too).

Here's the skeleton playground I used to reproduce the error (hopefully the same error) and find a modification the compiler accepted. That's about all I did -- I didn't analyze the logic at all or see if using the same lifetime in most places made the best sense, etc. Hopefully it points you in a useful direction.

1 Like

Thank you @quinedot , I updated the code and now it at least compiles :slight_smile:

But I don't fully understand all the code I wrote :rofl:

For example:
The following line.

pub trait Sortable<'a, ITER> where ITER : Iterator<Item = Node<'a>> + 'a 

It means the lifetime of returned Iterator must be covered by the Node's lifetime and the struct implements Sortable, right?
In short, Sortable > Iterator > Node , where > means lifetime overlapps the later

Well, it means that you're declaring a trait that's generic over a lifetime 'a and a type ITER, and ITER cannot be bound by a lifetime shorter than 'a, and ITER also implements Iterator with an associated type of Item = Node<'a>. All 'a must be the same for implementations of the trait. Coercion will often see you through, but sometimes you need to give things separate lifetimes (or just not bind lifetimes) so that the bounds of one won't force the bounds of the other.

Here's a contrived example of that happening.

Do you hit a problem if you drop the + 'a here? In this case, ITER is a generic type, not a trait object, so there is no default lifetime.

1 Like

Thanks again, it works well so far. I am trying to understand the complicated lifttime annotation

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.