I want to create a structure that serves as a wrapper for a global 'static
constant singleton. To do so, I created a struct Wrapper
containing a pointer to T
.
fn main() {
let s = Box::new(TestStruct {}) as Box<dyn TestTrait>;
let l = Wrapper::new(s);
tokio::spawn(async move { l.run().await });
}
struct Wrapper<T: Send + Sync + 'static> {
ptr: *const T,
// _phantom: std::marker::PhantomData<T>, // Use instead of ptr for tests
}
impl<T: Send + Sync + 'static> Wrapper<T> {
pub fn new(item: T) -> Self {
todo!();
}
}
impl<T: Send + Sync + 'static> std::ops::Deref for Wrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
todo!();
}
}
unsafe impl<T: Send + Sync + 'static> Sync for Wrapper<T> {}
unsafe impl<T: Send + Sync + 'static> Send for Wrapper<T> {}
trait TestTrait: Send + Sync {
fn run(&self) -> futures::future::BoxFuture<()>;
}
struct TestStruct {}
impl TestTrait for TestStruct {
fn run(&self) -> futures::future::BoxFuture<()> {
todo!();
}
}
error[E0477]: the type `std::boxed::Box<dyn TestTrait>` does not fulfill the required lifetime
--> src/main.rs:4:5
|
4 | tokio::spawn(async move { l.run().await });
| ^^^^^^^^^^^^
|
= note: type must satisfy the static lifetime
The problem is strange because if I remove unsafe impls
and replace ptr
with _phantom
, the program compiles. It looks like adding an unsafe impl
with a 'static
lifetime breaks some internal checks.
To sum up:
- no pointer in struct, no
unsafe impl
s - no error - pointer in struct, no
unsafe impl
s - error, becauseptr
is notSync
+Send
, that's fine - no pointer in struct,
unsafe impl
s - error, not'static
(???) - pointer in struct,
unsafe impl
s - error, not'static
(???)
I've read How do I create a global, mutable singleton? and How can you make a safe static singleton in Rust?. I'm not interested in how to make a global singleton, I'm curious why my example won't compile, whether it is compiler bug or where exactly I am wrong in my code.