Consider, on the other hand, that this means that the type of this function is not knowable just from looking at the defining crate, requiring an extra jump to the declaration.
Or, imagine that you change the types in a trait you own, and your implementation for your own type uses function signature inference. There is a small chance that the change somehow manages to still type-check, so you now how to rely on tests to catch the change. For example:
trait T {
fn f(x: i32, y: i32) -> i32;
}
impl T for K {
fn f(x: _, y: _) -> _ {
x + y
}
}
If you changed the signature of f to be fn(String, &str) -> String, you now cause an allocation to happen in a distant function. This is a contrived example, but shows the value of repeating yourself in the impl for both reading code and changing it.