The thing about Rust’s type inference that seems wild to anyone who hasn’t seen Hindley-Milner/ML style type systems before is that it’s “bidirectional” (in quotes because that’s not a proper type theory term as far as I know). The type of the left-side of an assignment can determine the type (and behavior!) of the right side. For instance, this is ambiguous:
let foo = [("a", 1), ("b", 2)].into_iter().collect();
The expression creates an iterator over the (letter, number)
pairs, and collect()
stores the elements in a newly created container. But which container type? Here are two valid variants:
let foo: Vec<_> = [("a", 1), ("b", 2)].into_iter().collect();
This creates a vector with items ("a", 1)
and ("b", 2)
.
let foo: HashMap<_, _> = [("a", 1), ("b", 2)].into_iter().collect();
This creates a mapping where "a"
and "b"
are keys, and 1
and 2
are the corresponding values.
Playground link in case you’d like to mess with this concept: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=76f999f4db600415643b0c58c19c69b7