title: How do you cast trait objects with an Arc<Mutex<...>>?
body: <p>I am trying to call a function which takes a pointer to a <code>Mutex</code> of some trait object, and I want to be able to implement the trait for the <code>Mutex</code> of that trait object to allow treating the <code>Mutex</code> as an instance of the trait object for abstraction.</p>
  
  <p>To give an example of this, imagine an <code>Event</code> listener setup as such:</p>
  
  <pre><code>use std::sync::{Arc, Mutex, Weak};
  
  // Define a simple event
  trait Event: Send + Sync + 'static {}
  impl Event for String {}
  
  
  // Define the listener interface
  trait Listener&lt;E: Event&gt; {
      fn notify(&amp;self, event: &amp;E);
  }
  
  // Extend the listener interface to listenrs wrapped by a mutex
  impl&lt;E: Event&gt; Listener&lt;E&gt; for Mutex&lt;Listener&lt;E&gt;&gt; {
      fn notify(&amp;self, event: &amp;E) {
          self.lock().unwrap().notify(event);
      }
  }
  
  
  // Contrived thing to listen for messages
  struct Console;
  impl Listener&lt;String&gt; for Console {
      fn notify(&amp;self, event: &amp;String) {
          println!("{}", event);
      }
  }
  
  
  // Simple function which may be called asynchronously and then sends a message
  // when it is complete
  fn do_stuff(l: Arc&lt;Listener&lt;String&gt;&gt;) {
      // Would normally cast to a Weak&lt;...&gt; and then store in a list of listneners
      // For some sort of object
      let m = String::from("I did stuff!");
      l.notify(&amp;m);
  }
  
  fn main() {
      let l: Arc&lt;Mutex&lt;Console&gt;&gt; = Arc::new(Mutex::new(Console));
  
      let t1 = Arc::clone(&amp;l) as Arc&lt;Mutex&lt;Listener&lt;String&gt;&gt;&gt;; //this part is ok
      // Here is where we run into issues... This *should* be equvlient to
      // do_stuff(t1), but with the corercion explicit
      let t2 = Arc::clone(&amp;t1) as Arc&lt;Listener&lt;String&gt;&gt;;
      do_stuff(t2);
  
      // This is a simple, working example of it interpreting a Mutex&lt;Listener&lt;E&gt;&gt;
      // as just a Listener&lt;E&gt;
      let m = String::from("Somthing else...");
      (l as Arc&lt;Mutex&lt;Listener&lt;String&gt;&gt;&gt;).notify(&amp;m);
  }
  </code></pre>
  
  <p>(<a href="https://play.rust-lang.org/?gist=e73ccb2f4966aea6d1dfd2427c3e8c7f&amp;version=undefined" rel="nofollow noreferrer">Playground</a>)</p>
  
  <p>The issue is:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0277]: the trait bound `Listener&lt;std::string::String&gt;: std::marker::Sized` is not satisfied in `std::sync::Mutex&lt;Listener&lt;std::string::String&gt;&gt;`
    --&gt; src/main.rs:45:14
     |
  45 |     let t2 = Arc::clone(&amp;t1) as Arc&lt;Listener&lt;String&gt;&gt;;
     |              ^^^^^^^^^^^^^^^ `Listener&lt;std::string::String&gt;` does not have a constant size known at compile-time
     |
     = help: within `std::sync::Mutex&lt;Listener&lt;std::string::String&gt;&gt;`, the trait `std::marker::Sized` is not implemented for `Listener&lt;std::string::String&gt;`
     = note: required because it appears within the type `std::sync::Mutex&lt;Listener&lt;std::string::String&gt;&gt;`
     = note: required for the cast to the object type `Listener&lt;std::string::String&gt;`
  </code></pre>
  
  <p>Why this is the case? Since an <code>Arc</code> is a pointer to data, from my understanding, it should be able to point to a <code>Listener&lt;String&gt;</code> which happens to be a <code>Listener&lt;Mutex&lt;String&gt;&gt;</code>.</p>
  
  <p>I see at least two ways to avoid this, the first is to simply <code>impl Listener&lt;String&gt; for Mutex&lt;Listener&lt;String&gt;&gt;</code>, however, in the actual code this may require interdependence which should be avoided because the trait can only be implemented where the trait or structure is defined (and <code>Mutex</code> is not defined in my code).</p>
  
  <p>The second is to move the <code>Mutex</code> into the <code>Listener</code> object so the caller does not need to cast it at all. This would work, and may be a better solution. Despite this, I am curious as to either why the casting proposed does not work and or what can be changed to make it work.</p>