3

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 impls - no error
  • pointer in struct, no unsafe impls - error, because ptr is not Sync + Send, that's fine
  • no pointer in struct, unsafe impls - error, not 'static (???)
  • pointer in struct, unsafe impls - 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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
peku33
  • 3,628
  • 3
  • 26
  • 44
  • Notice that, apparently, you are about to save `*const Box<...>` in your wrapper, which, as soon as `Wrapper::new` exits, will be a dangling pointer. – kreo Apr 14 '20 at 07:49

0 Answers0