Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I have a static borrowed reference to a trait object?

Tags:

rust

traits

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?
}
like image 340
LorenVS Avatar asked Oct 29 '13 19:10

LorenVS


People also ask

How do you make a trait object in Rust?

We create a trait object by specifying some sort of pointer, such as a & reference or a Box<T> smart pointer, then the dyn keyword, and then specifying the relevant trait.

Does rust have dynamic dispatch?

Rust provides dynamic dispatch through a feature called 'trait objects'. Trait objects, like &Foo or Box<Foo> , are normal values that store a value of any type that implements the given trait, where the precise type can only be known at runtime.


1 Answers

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 is Sync if &T is Send. 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.

like image 169
Shepmaster Avatar answered Sep 25 '22 08:09

Shepmaster