title: Avoiding `Sync` for shared static variables
body: <p>I have the following definitions:</p>
  
  <pre><code>struct MyCustomFactory;
  
  trait Factory {
      fn new&lt;'a&gt;(entity: &amp;'a str) -&gt; Arc&lt;dyn Display + 'a&gt;
      where
          Self: Sized;
  }
  
  impl Factory for MyCustomFactory {
      fn new&lt;'a&gt;(entity: &amp;'a str) -&gt; Arc&lt;dyn Display + 'a&gt;
      where
          Self: Sized,
      {
          Arc::new(entity)
      }
  }
  </code></pre>
  
  <p>Higher level problem:</p>
  
  <p>I'm trying to create a global static (and immutable) map of strings to structs which implement the <code>Factory</code> trait. The goal is that for any value member of the map, I can treat it like a <code>Factory</code>, call <code>new</code> against it, and in turn will get <em>something</em> back that (in this case) implements the <code>Display</code> trait.</p>
  
  <p>I have the following:</p>
  
  <pre class="lang-rust prettyprint-override"><code>static ITEMS: Lazy&lt;BTreeMap&lt;&amp;'static str, Arc&lt;dyn Factory&gt;&gt;&gt; =
      Lazy::new(|| {
          let mut map = BTreeMap::new();
          let value = Arc::new(MyCustomFactory) as Arc&lt;dyn Factory&gt;;
          map.insert("foo", value);
          map
      });
  </code></pre>
  
  <p>The compiler complains with:</p>
  
  <pre class="lang-none prettyprint-override"><code>77 | / static ITEMS: Lazy&lt;BTreeMap&lt;&amp;'static str, Arc&lt;dyn Factory&gt;&gt;&gt; =
  78 | |     Lazy::new(|| {
  79 | |         let map = BTreeMap::new();
  80 | |         let value = Arc::new(MyCustomFactory) as Arc&lt;dyn Factory&gt;;
  ...  |
  88 | |     });
     | |_______^ `(dyn Factory + 'static)` cannot be shared between threads safely
     |
     = help: the trait `std::marker::Sync` is not implemented for `(dyn Factory + 'static)`
     = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc&lt;(dyn Factory + 'static)&gt;`
     = note: required because of the requirements on the impl of `std::marker::Send` for `alloc::collections::btree::node::Root&lt;&amp;'static str, std::sync::Arc&lt;(dyn Factory + 'static)&gt;&gt;`
     = note: required because it appears within the type `std::collections::BTreeMap&lt;&amp;'static str, std::sync::Arc&lt;(dyn Factory + 'static)&gt;&gt;`
     = note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::imp::OnceCell&lt;std::collections::BTreeMap&lt;&amp;'static str, std::sync::Arc&lt;(dyn Factory + 'static)&gt;&gt;&gt;`
     = note: required because it appears within the type `once_cell::sync::OnceCell&lt;std::collections::BTreeMap&lt;&amp;'static str, std::sync::Arc&lt;(dyn Factory + 'static)&gt;&gt;&gt;`
     = note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::sync::Lazy&lt;std::collections::BTreeMap&lt;&amp;'static str, std::sync::Arc&lt;(dyn Factory + 'static)&gt;&gt;&gt;`
     = note: shared static variables must have a type that implements `Sync`
  </code></pre>
  
  <p>Things I have tried:</p>
  
  <ul>
  <li><p><strong>Implement <code>Sync</code> against the trait</strong>: Declaring the trait to have <code>trait Factory : Sync</code>, (meaning all items which implement the trait, must implement <code>Sync</code>) and/or defining:</p>
  
  <pre class="lang-none prettyprint-override"><code>   |
  66 | unsafe impl Sync for dyn Factory {}
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
  </code></pre></li>
  <li><p><strong>Wrapping <code>Arc&lt;dyn Factory&gt;</code></strong>: I've tried using <code>Mutex</code> / <code>RefCell</code> / <code>OnceCell</code> and others, all resulting in the same error. It seems like there should be a way to treat the underlying <code>MyCustomFactory</code> as a Singleton that can be locked around. It's fine (and expected) that's there's only once instance of this struct globally.</p></li>
  </ul>