Проблема с типами тут.
Тип
fn() -> u8
- это указатель на функцию. В него можно записать или обычную функцию с подходящей сигнатурой или замыкание, которое ничего не замыкает:
fn some_func() -> u8 {
0
}
let f: fn() -> u8 = some_func;
let f: fn() -> u8 = || 0;
Если же замыкание что-то замыкает (захватывает переменные из окружения), то это уже анонимная структура, хранящая в себе все захваченные значения (или ссылки на них), и у этой структуры просто перегружен оператор круглые скобки через трейты Fn/FnMut/FnOnce. Притом, так как компилятор генерирует для каждого замыкания в коде свою анонимную структуру, у каждого замыкания будет свой уникальный тип.
Если массив замыканий полностью формируется в цикле, то замыкания будут одного типа и все скомпилируется:
fn main() {
let mut funcs = Vec::with_capacity(3);
for i in 1u8..=3 {
funcs.push(move || i);
}
for i in 0..3 {
println!("{}", funcs[i]());
}
}
P.S. для рэнжей есть литералы, не нужно их создавать через
std::ops::RangeInclusive::<u8>::new