Reference must be valid for the lifetime


#1

Hi, I try to translate this C++ code http://cpp.sh/2boo to Rust http://is.gd/iG6RdW
Help to put lifetime correctly.
Thanks.


What needs to be explained about lifetime parameters
#2

Your lvl2 function had the wrong signature. If you change it to

fn lvl2<'a, 'b>(foo: &Foo<'a, 'b>) -> &'b i32 {

then it works. If you want a detailed explanation, please post a detailed question.


#3

I want to understand how lifetime works with nested objects, for example http://cpp.sh/4j6p
I am trying http://is.gd/nIrM4o


#4

This is the best I could come up with for now. The problem is that the lifetimes of p1 and p2 are vastly different and, so I didn’t figure out how they could be shared. You will then have to declare them both in Bar, for the same reason, plus one extra for the additional reference:

struct Bar<'a: 'r, 'b: 'r, 'r> {
  foo: &'r Foo<'a, 'b>
}

'a and 'b are tied to ´’r´ to make sure the content of Foo lives at least as long as the reference. You will then have to use these lifetimes in ´lvl2´:

fn lvl2<'a, 'b, 'r>(bar: &Bar<'a, 'b, 'r>) -> &'b i32 {
  return bar.foo.p2;
}

The compiler is clever enough to figure out an extra lifetime for &Bar. It should not live as long as 'b, which would be too long. That’s about it.

Oh, and you don’t have to box everything (or anything in this case), by the way :slight_smile:


#5

this is lifetime of lifetime, or what?

ok :slight_smile:


#6

Almost. Is more like 'a includes 'r or inherits from 'r (you will see the same notation for trait inheritance) meaning that 'a must be at least as long as 'r.

Just to continue on my note, to explain how I was thinking: You can actually get rid of some complexity by removing some indirection: http://is.gd/H1AwAE

Rust will move values by default, unless they implement Copy (like numbers), meaning that you don’t need any kind of pointer to make sure that you only have one instance of each object. That’s why I removed any occurrence of Box. I chose to remove the reference to Foo in Bar for about the same reason. They are not used in any other way, so you can just merge them together.

I realize that your actual use may be more complicated that this, but I just wanted to elaborate in case you didn’t know. :slight_smile:


#7

Oh, for 3,4,5 nesting will be awful :frowning:

Thank you li_obk and ogeon


#8

It may be possible to reuse 'r on deeper levels: bar: &'r Bar<'a, 'b, 'r> (totally untested). Or just remove the reference, as above, if it’s not absolutely necessary.


#9

second variant is much better, thanks