let mut x = HashMap::new();
x.insert(1, 2);
Note that nowhere did we need to specify the concrete type of the HashMap; the compiler sees that you eventually insert numbers into the map so it uses that information to fill in the generic type parameters for the key and value.People always complain about Rust's type system being verbose- well, this makes it less verbose. It knows what you need from the function call, so it doesn't make you say it. And as an added benefit, if the required type ever changes in a way that can still be generated by the provided code (eg. the function you're passing to needs a different length), you won't need to update any explicit type annotations at the call-site.
If that's ever undesirable - you want to be very precise about your code - well, then you can do that too by specifying the generic parameters explicitly.
let numbers = [0, 1, 2];
let doubled = numbers.map(|x| x * 2);
You wouldn't want to have to explicitly type out the length of the second array.> What's a sane/legit use case of such inferring in general?
Depends how you interpret "such inferring"
let foobar = Default::default();
do_something_with(foobar); // where do_something_with takes a FooBar param
One I often use in unit tests: fn generate_ids<const N: usize>() -> [Id; N] { ... }
let [id_button, id_label, id_thing, id_other_thing] = generate_ids();
(before const generics were stabilized, the above code instead had multiple utility functions, eg generate_2_ids, generate_3_ids, etc)In other languages, this can be a brittle/expensive operation due to meh tooling. But with Rust, it tends to "just work".
Online viewers of source e.g. Github and such don't have all this information exposed yet, but they're incrementally getting there. For instance, "go to definition" works for Rust code in Github.
One could imagine a generic file format included as an artifact in source control, that online viewers could consume, to annotate spans of source code. Go to definition, show expanded type, etc.