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:
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:
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, andcollect()
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, and1
and2
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