error[E0308]: mismatched types
--> src/main.rs:7:14
|
4 | let closures_1 = || {};
| ----- the expected closure
...
7 | let v2 = vec![closures_1, closures_2,]; // ❌
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice, found array of 2 elements
|
= note: expected struct `Box<[[closure@src/main.rs:4:22: 4:27]], _>`
found struct `Box<[fn(); 2], std::alloc::Global>`
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
Neither of the closures captures an environment, so they coerce to the function pointer type fn(). (If one or both of them had captures then neither example would compile.) It looks like something in the expansion of the vec macro is blocking that coercion. If you cast explicitly like vec![closures_1 as fn(), closures_2 as fn()] there's no error.
Edit: experimenting with manually expanding vec!, it looks like the coercion is blocked by box expressions: this compiles
fn main() {
let f = || {};
let g = || {};
let v = <[_]>::into_vec(Box::new([f, g]));
}
but this doesn't (nightly-only)
#![feature(box_syntax)]
fn main() {
let f = || {};
let g = || {};
let v = <[_]>::into_vec(box [f, g]);
}
I think this is #22405 / the downside listed in RFC 809, but didn't spend too much time digging.
Not sure if it's more desirable to keep the presumed optimization or to make the stdlib stop "cheating" in this case (by exploiting capabilities no longer expected to be made stable in their currrent form).