Error while using a function pointer

I guess I am missing something fundamental about function pointers here:

use std::sync::Arc;

pub struct A(usize);

pub struct B(usize);

pub type Executor = fn(a: &A, b: &mut B, factor: usize);

fn main() {
    let v = create_vector();
    let (a, f) = v.get(0).unwrap();
    let mut b = B(1);
    f(&a, &mut b, 0);
}

fn todo_executor(_a: &A, _b: &mut B, _factor: usize) {
    todo!();
}

fn create_vector() -> Arc<Vec<(A, Executor)>> {
    let v = vec![
        (A(0), todo_executor),
    ];
    Arc::new(v)
}

Playground link

Can someone explain the following error to me? I really don't understand what's happening. :confused:

error[E0308]: mismatched types
   --> src/main.rs:24:14
    |
24  |     Arc::new(v)
    |     -------- ^ expected `Vec<(A, fn(&A, &mut B, usize))>`, found `Vec<(A, ...)>`
    |     |
    |     arguments to this function are incorrect
    |
    = note: expected struct `Vec<(A, for<'a, 'b> fn(&'a A, &'b mut B, _))>`
               found struct `Vec<(A, for<'a, 'b> fn(&'a A, &'b mut B, _) {todo_executor})>`
note: associated function defined here
   --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:392:12
    |
392 |     pub fn new(data: T) -> Arc<T> {
    |            ^^^

1 Like
-        (A(0), todo_executor),
+        (A(0), todo_executor as Executor),

Free function has it's own (unnamable, zero sized) type. You have to cast them to function pointer explicitly here, since type inference can't go backwards too far.

Annotating v works as well.

let v: Vec<(A, Executor)> = vec![
        (A(0), todo_executor),
    ];

2 Likes

I guessed it had something to do with each function having its own type but I didn't think about explicitly casting. :smiling_face_with_tear: Well, simpler than I guessed, thank you very much.

It's often enough to let the compiler know that some kind of cast or coercion is required.

    let v = vec![
        (A(0), todo_executor as _),
    ];
1 Like