Can I have a static borrowed reference to a trait object?
Is there a way for me to obtain a static borrowed reference to a struct's implementation of a trait:
trait Trait {}
struct Example;
impl Trait for Example {}
This works fine:
static instance1: Example = Example;
This also works fine:
static instance2: &'static Example = &Example;
But this doesn't work:
static instance3: &'static Trait = &Example as &'static Trait;
It fails thus:
error[E0277]: the trait bound `Trait + 'static: std::marker::Sync` is not satisfied in `&'static Trait + 'static`
--> src/main.rs:10:1
|
10 | static instance3: &'static Trait = &Example as &'static Trait;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Trait + 'static` cannot be shared between threads safely
|
= help: within `&'static Trait + 'static`, the trait `std::marker::Sync` is not implemented for `Trait + 'static`
= note: required because it appears within the type `&'static Trait + 'static`
= note: shared static variables must have a type that implements `Sync`
Alternatively, is there a way to obtain a borrowed static pointer to a trait from a global borrowed static pointer to a struct:
static instance2: &'static Example = &Example;
fn f(i: &'static Trait) {
/* ... */
}
fn main() {
// how do I invoke f passing in instance2?
}
Yes, you can, if the trait also implements Sync
:
trait Trait: Sync {}
struct Example;
impl Trait for Example {}
static INSTANCE3: &dyn Trait = &Example;
Or if you declare that your trait object also implements Sync
:
trait Trait {}
struct Example;
impl Trait for Example {}
static INSTANCE3: &(dyn Trait + Sync) = &Example;
Types that implement Sync
are those
[...] for which it is safe to share references between threads.
This trait is automatically implemented when the compiler determines it's appropriate.
The precise definition is: a type
T
isSync
if&T
isSend
. In other words, if there is no possibility of undefined behavior (including data races) when passing&T
references between threads.
Since you are sharing a reference, any thread would be able to call methods on that reference, so you need to ensure that nothing would violate Rust's rules if that happens.