# HashMap from array of tuples problem

(This comes from AoC) Could someone tell me why this compiles:

``````let instructions: &[(_, fn(r: &mut [usize], a: usize, b: usize) -> usize)] = &[
("addr", |r, a, b| r[a] + r[b]),
("addi", |r, a, b| r[a] + b),
("mulr", |r, a, b| r[a] * r[b]),
("muli", |r, a, b| r[a] * b),
("banr", |r, a, b| r[a] & r[b]),
("bani", |r, a, b| r[a] & b),
("borr", |r, a, b| r[a] | r[b]),
("bori", |r, a, b| r[a] | b),
("setr", |r, a, _| r[a]),
("seti", |_, a, _| a),
("gtir", |r, a, b| (a > r[b]).into()),
("gtri", |r, a, b| (r[a] > b).into()),
("gtrr", |r, a, b| (r[a] > r[b]).into()),
("eqir", |r, a, b| (a == r[b]).into()),
("eqri", |r, a, b| (r[a] == b).into()),
("eqrr", |r, a, b| (r[a] == r[b]).into())];

let instructions: HashMap<_, _> = instructions.iter().cloned().collect();
``````

And this doesnâ€™t?

``````let instructions2: HashMap<&str, fn(r: &mut [usize], a: usize, b: usize) -> usize> = [
("addr", |r, a, b| r[a] + r[b]),
("addi", |r, a, b| r[a] + b),
("mulr", |r, a, b| r[a] * r[b]),
("muli", |r, a, b| r[a] * b),
("banr", |r, a, b| r[a] & r[b]),
("bani", |r, a, b| r[a] & b),
("borr", |r, a, b| r[a] | r[b]),
("bori", |r, a, b| r[a] | b),
("setr", |r, a, _| r[a]),
("seti", |_, a, _| a),
("gtir", |r, a, b| (a > r[b]).into()),
("gtri", |r, a, b| (r[a] > b).into()),
("gtrr", |r, a, b| (r[a] > r[b]).into()),
("eqir", |r, a, b| (a == r[b]).into()),
("eqri", |r, a, b| (r[a] == b).into()),
("eqrr", |r, a, b| (r[a] == r[b]).into())]
.iter().cloned().collect();
``````

The second gives the errors:

error[E0282]: type annotations needed
â€“> â€¦\test.rs:26:19
|
26 | (â€śaddrâ€ť, |r, a, b| r[a] + r[b]),
| ^ consider giving this closure parameter a type
|
= note: type must be known at this point

error[E0277]: a collection of type `std::collections::HashMap<&str, for<'r> fn(&'r mut [usize], usize, usize) -> usize>` cannot be built from an iterator over elements of type `(&str, [closure@...\test.rs:35:18: 35:29])`
â€“> â€¦\test.rs:42:26
|
42 | .iter().cloned().collect();
| ^^^^^^^ a collection of type `std::collections::HashMap<&str, for<'r> fn(&'r mut [usize], usize, usize) -> usize>` cannot be built from `std::iter::Iterator<Item=(&str, [closure@...\test.rs:35:18: 35:29])>`
|
= help: the trait `std::iter::FromIterator<(&str, [closure@...\test.rs:35:18: 35:29])>` is not implemented for `std::collections::HashMap<&str, for<'r> fn(&'r mut [usize], usize, usize) -> usize>`

Because Rust canâ€™t infer the types of the closures with that much indirection.

2 Likes