Type inference around Arc::clone

Viewed 43

I don't understand why this compiler error happens. Here's the code:

use std::sync::Arc;

trait MyTrait {}

struct MyStruct(i32);

impl MyTrait for MyStruct {}

fn takes_arc_dyn(arc: Arc<dyn MyTrait>) {
    // ...
}

fn main() {
    let arc = Arc::new(MyStruct(0));
    takes_arc_dyn(Arc::clone(&arc));
}

The error is:

error[E0308]: mismatched types
  --> <source>:17:30
   |
17 |     takes_arc_dyn(Arc::clone(&arc));
   |                              ^^^^ expected trait object `dyn MyTrait`, found struct `MyStruct`
   |
   = note: expected reference `&Arc<dyn MyTrait>`
              found reference `&Arc<MyStruct>`

If I change the offending line to either of these, the error goes away and the code behaves as expected:

takes_arc_dyn(Arc::clone(&arc) as Arc<MyStruct>);
takes_arc_dyn(Arc::clone(&arc) as Arc<dyn MyTrait>);

Assigning the clone to a variable first also fixes it:

fn main() {
    let arc = Arc::new(MyStruct(0));
    let clone = Arc::clone(&arc);
    takes_arc_dyn(clone);
}

I assume this is some subtle thing about type inference that I haven't learned, but I don't understand (a) why this is an error in the first place, and (b) why any of those three fixes works.

In particular, I find it strange that in the erroring code, the compiler is apparently refusing to accept an Arc<MyStruct> when it expects an Arc<dyn MyTrait>, but in both versions with the as cast, it's doing exactly that with no complaint.

I assume assigning the clone to a variable, which seems like it should be a no-op, meaningfully changes things w.r.t. type inference, but I'd be interested to know the exact details.

0 Answers
Related