There was some discussion of this in IRC yesterday, which left me feeling vaguely dissatisfied.
The question was:
How do you define a lifetime on a struct to restrict its contents to only things that live as long as 'itself'.
i.e. a 'self sort of thing.
My initial reaction was: you can't.
If you create a struct Foo<'a>, the lifetime associated with it is inferred from the references it contains; unless the struct contains a reference to itself (impossible), you can't have this sort of 'self lifetime.
There was a bunch of chatter about it, and I ended up writing this playground as a result:
#[derive(Debug)]
struct Bar;
#[derive(Debug)]
struct Foo<'a> {
a:&'a Bar,
b:&'a Bar
}
fn factory<'a>(v1:&'a Bar, v2: &'a Bar) -> Foo<'a> {
return Foo {
a: v1,
b: v2
};
}
fn main() { // <---- Let's call this block lifetime 'one
let a = Bar;
let c = &a; // <-- C has lifetime 'one
{ // <------------ Let's call this block lifetime 'two
let b = Bar;
let mut foo1 = factory(c, c);
foo1.b = &b;
let mut foo2 = factory(&b, &b);
foo2.a = &a;
println!("{:?}", foo1);
println!("{:?}", foo2);
}
}
However, I'm now more confused rather than less.
So, in a strict sense in the above:
chas'one&bhas'two'static>'one>'two(that is,'twois bounded by'one).foo1has'onefoo2has'two
Now, my confusion:
Foo<'a> indicates that 'a is the minimum lifetime bound that can be contained by the instance of Foo.
Since
'one>'two,foo2should be able contain a&'one a; this works.Since
'two>'one,foo1should not be able to contain&'two b; however, this works.
Why?
It would appear my confusion results from one of two misconceptions; either:
The instance of
foo1is in factFoo<'two>, notFoo<'one>.I don't understand why this would be the case, since it is manufactured in
factory<'a>where<'a>is the lifetime ofc; which is'one, not'two. There's absolutely no wayccan be&'twoin the example above. The lifetime'twois not available in the function factory whereFoois created.
2) Struct lifetimes don't work how I understand them to work; i.e. a lifetime of 'a on a Foo instance can somehow change between after the instance is created (e.g. on a move?)
...but I don't know which one.