error[E0308]: mismatched types
--> src/main.rs:8:10
|
8 | test(&Arc::new(|| {}))
| ---- ^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure
| |
| arguments to this function are incorrect
|
= note: expected reference `&Arc<(dyn Fn() + 'static)>`
found reference `&Arc<[closure@src/main.rs:8:20: 8:22]>`
note: function defined here
--> src/main.rs:4:4
|
4 | fn test(f: &Arc<dyn Fn()>) {}
| ^^^^ -----------------
but it works fine by writing:
fn test(f: Arc<dyn Fn()>) {} // no reference here
fn main() {
test(Arc::new(|| {}))
}
So why the reference type cannot be converted implicitly? And if I insist to using the first version of test, how to pass a closure easily? (Currently, I have to manually convert it to &Arc<dyn Fn()> by using as. And it needs to annotate the parameter version if the Fn take parameters.)
An Arc<closure> takes up 8 bytes because it consists of a pointer to the data inside the arc. An Arc<dyn Fn> takes up 16 bytes because it consists of a pointer to the data inside the arc and a pointer to the vtable for the function. You cannot make the conversion because the immutable reference is unable to modify the value it points at.
I'd say so, as Arc is a pointer itself and cheaply clonable.
I've hit the same problem with type inference and type coercion myself not long ago and I think it is related to your problem. I.e. the problem being that the compiler is unable to infer the right type as a trait object (dyn Fn() in this case) when we want to downcast a concrete type (the type of the closure in this example) implicitly.
You can find the topic here:
@quinedot and @steffahn wrote some very insightful posts in that topic IMO