I'm trying to implement a generic "id container" struct that is strongly typed. Basically its a struct with a generic parameter to hold the type and a small payload.
Since the generic parameter is unused within the struct, I need to add a PhantomData<T>
member. When this parameter's type does not have a 'static
lifetime, this affects the entire struct.
The following code that reproduces this issue:
use std::marker::PhantomData;
struct Tag<T>(usize, PhantomData<T>);
struct WithRef<'a>(&'a i32);
trait SomeTrait {}
impl<T> SomeTrait for Tag<T> {}
fn ok() {
let obj = Tag::<i32>(1, PhantomData);
let _dyn_obj: &(dyn SomeTrait + 'static) = &obj;
}
fn bad<'b>() {
let obj = Tag::<WithRef<'b>>(2, PhantomData);
let _dyn_obj: &(dyn SomeTrait + 'static) = &obj;
}
outputs this compiler error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src\main.rs:15:15
|
15 | let obj = Tag::<WithRef<'b>>(2, PhantomData);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 14:8...
--> src\main.rs:14:8
|
14 | fn bad<'b>() {
| ^^
note: ...so that the expression is assignable
--> src\main.rs:15:15
|
15 | let obj = Tag::<WithRef<'b>>(2, PhantomData);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Tag<WithRef<'_>>`
found `Tag<WithRef<'b>>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
--> src\main.rs:16:48
|
16 | let _dyn_obj: &(dyn SomeTrait + 'static) = &obj;
| ^^^^
= note: expected `&(dyn SomeTrait + 'static)`
found `&dyn SomeTrait`
PhantomData in std::marker - Rust mentions that:
If your struct does not in fact own the data of type T, it is better to use a reference type, like PhantomData<&'a T> (ideally) or PhantomData<*const T> (if no lifetime applies), so as not to indicate ownership.
But neither PhantomData<&'a T>
nor PhantomData<*const T>
makes this code compile.
Is there any way to keep the generic parameter without loosing the 'static
lifetime?
Thanks!