Reputation: 63
use std::marker::PhantomData;
struct S<'a, A> {
_phantom: PhantomData<*const A>,
value: &'a i32,
}
fn foo<'a, A>(value: &'a i32) {
let s: &'a S<'a, A> = &S {
_phantom: PhantomData,
value,
};
}
fn main() {}
Struct S
actually don't owns generic argument A
, so lifetime of A
don't relate to lifetime of S
. However Rust compiler output error in let s: &'a S<'a, A>
:
the parameter type `A` may not live long enough
...so that the reference type `&'a S<'a, A>` does not outlive the data it points at
consider adding an explicit lifetime bound...: `A: 'a`
Why is lifetime of A
bounded? Can we get independent A
from the lifetime of S
?
(Edit) The above code has another problem about reference to S
in foo
. More healthy code is:
use std::marker::PhantomData;
struct S<'a, A> where Self: 'a {
_phantom: PhantomData<*const A>,
value: &'a i32,
}
fn foo<'a, A>(value: &'a i32) {
let s: S<'a, A> = S {
_phantom: PhantomData,
value,
};
}
fn main() {}
Upvotes: 2
Views: 266
Reputation: 349
[in
let s: &'a S<'a, A>
] Why is lifetime ofA
bounded [to'a
]?
When you write &'x T
it implies T: 'x
and is read as Any type [including reference types] that T contain must be valid during 'x
.
In &'a S<'a, A>
that basically means:
S<'a, A>: 'a
which means:
&'a i32: 'a
=> 'a: 'a
PhantomData<*const A>: 'a
=> *const A: 'a
=> A: 'a
.But when looking at our environment (the fn signature fn foo<'a, A>(value: &'a i32)
) the A: 'a
is not true hence the error.
Can we get independent
A
from the lifetime ofS
?
[Inside of fn foo
I suppose?]
You can remove 'a
lifetime from the reference: let s: &S<'a, A>
to get build passing. In this case compiler will use a special unnamed lifetime 'free_region
:
let s: &'free_region S<'a, A>
where 'free_region
is any lifetime in which S<'a, A>
is valid i.e. S<'a, A>: 'free_region
which means 'a: 'free_region
and A: 'free_region
Consider adding a second input lifetime 'region
:
fn foo<'a, 'region, A>() {
let s: &'region S<'a, A>;
}
We see that both of lifetimes and A
are unrelated to each other. And rustc gives us a reasonable error:
error[E0491]: in type `&'region S<'a, A>`, reference has a longer lifetime than the data it references
--> src/main.rs:9:12
|
9 | let s: &'region S<'a, A>;
| ^^^^^^^^^^^^^^^^^
|
note: the pointer is valid for the lifetime `'region` as defined on the function body at 8:12
--> src/main.rs:8:12
|
8 | fn foo<'a, 'region, A>(value: &'a i32) {
| ^^^^^^^
note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 8:8
--> src/main.rs:8:8
|
8 | fn foo<'a, 'region, A>(value: &'a i32) {
| ^^
We must provide 'a: 'region
and A: 'region
bounds either in where
clauses:
fn foo<'a, 'region, A>()
where
'a: 'region,
A: 'region,
// or just simply
S<'a, A>: 'region,
{
let s: &'region S<'a, A>;
}
or via RFC 2093: Infer T: 'x
outlives requirements on structs
fn foo<'a, 'region, A>(
_: &'region &'a i32,
_: &'region PhantomData<*const A>,
// or just simply
_: &'region S<'a, A>,
) {
let s: &'region S<'a, A>;
}
Upvotes: 1