1

If I try to make a vector of function pointers, the compiler always complains about wrong types (although I don't declare any type explicitly):

fn abc() {}

fn def() {}

fn main()
{
    let a = vec![abc, def];
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ef52fe778db1112433d20dd02b3d0b54

error[E0308]: mismatched types
 --> src/main.rs:5:13
  |
5 |     let a = vec![abc, def];
  |             ^^^^^^^^^^^^^^ expected slice, found array of 2 elements
  |
  = note: expected struct `Box<[fn() {abc}], _>`
             found struct `Box<[fn(); 2], std::alloc::Global>`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `tes`

To learn more, run the command again with --verbose.
zvavybir
  • 1,034
  • 6
  • 15

2 Answers2

6

I believe Rust tries to give unique types to functions, so just specify that it's a function pointer Vec. This also avoids the additional indirection and allocation of Box<dyn Fn()>:

fn abc() {}
fn def() {}

fn main() {
    let a: Vec<fn()> = vec![abc, def];
}

Alternatively, "cast" the first and the rest can be inferred:

fn abc() {}
fn def() {}

fn main() {
    let a = vec![abc as fn(), def];
}
Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • Minor correction: it avoids the additional allocation, but still has a degree of indirection (the "pointer" part of "function pointer"). Although arguably it's still *less* indirection, since you don't have to follow both a vtable pointer *and* a function pointer. – trent Mar 15 '21 at 16:49
2

The two functions have distinct types, you should be able to explicitly Box them and cast to Box<dyn Fn()>

fn abc() {}
fn def() {}
fn main()
{
    let a = vec![Box::new(abc) as Box<dyn Fn()>, Box::new(def) as Box<dyn Fn()>];
}
sebpuetz
  • 2,430
  • 1
  • 7
  • 15