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.