Martin Jonsson
Martin Jonsson

Reputation: 138

Why do I get "error[E0308]: mismatched types" when the function pointer types match exactly

I've got a scenario where I want to pass a function pointer (or closure) that takes a mutable reference to a struct, as a way of letting the caller initialize that struct for me.

The (very simplified) code looks like this:

use std::future::Future;

struct Data {
    value: u32
}

async fn initialize(data: &mut Data) {
    // ... do some async work ...
    data.value = 1;
}

fn do_work<Fut>(init: fn(&mut Data) -> Fut) 
where
    Fut: Future<Output = ()>,
{
    pollster::block_on(async {
        let mut data = Data { value:0 };
        init(&mut data).await;
        // ... do other stuff with `data`
    })
}

fn main() {
    do_work(initialize);
}

And I get the compiler error:

error[E0308]: mismatched types
  --> src/main.rs:29:13
   |
29 |     do_work(initialize);
   |     ------- ^^^^^^^^^^ one type is more general than the other
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected fn pointer `for<'a> fn(&'a mut Data) -> _`
                 found fn item `for<'a> fn(&'a mut Data) -> impl Future<Output = ()> {initialize}`
note: function defined here
  --> src/main.rs:17:4
   |
17 | fn do_work<Fut>(init: fn(&mut Data) -> Fut) 
   |    ^^^^^^^      --------------------------

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

but I can not find where I've gone wrong. I'm suspecting there's something whacky happening with Higher-Ranked Trait Bounds since there's a for<'a> in there, but I can't figure out why it's not correct.

Playground link.

If I don't make initialize async, it works just as expected. Maybe there's something going on with Future<Output = ()>?

Edit:

A similar question is "Expected fn item, found a different fn item" when working with function pointers, but as @PitaJ pointed out this is not the same thing as in this case I've got a fn item and a fn pointer and not two fn items, and here there's a generic function output.

Upvotes: 1

Views: 53

Answers (0)

Related Questions