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:
c
has'one
&b
has'two
'static
>'one
>'two
(that is,'two
is bounded by'one
).foo1
has'one
foo2
has'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
,foo2
should be able contain a&'one a
; this works.Since
'two
>'one
,foo1
should 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
foo1
is 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 wayc
can be&'two
in the example above. The lifetime'two
is not available in the function factory whereFoo
is 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.