The declaration of a function argument is just a special case of variable declarations in Rust, therefore the answer to your question lies in variable declaration in general.
Let us start with C:
a b = 1;
a = 2;
From a grammar point of view, C is not quite regular:
- in
a b = 1;, a is the type and b is the name of a new variable being declared (and initialized)
- in
a = 1;, a is the name of a variable that was declared previously and is now either initialized or assigned a new value (overwriting the previous one).
Therefore, in C, knowing whether a is a type or a variable name requires looking ahead (ie, if followed by another variable then it's a type, otherwise it's a variable).
Now, in Rust:
let a = 1;
a = 2;
The syntax for introducing a new variable requires using the let keyword, there is no ambiguity and no need to look ahead to disambiguate. This is all the more important because of shadowing in Rust (let a = ...; let a = a.foo;).
The question was about types though, so let's extend the example:
let a: b = 1;
a = 2;
In this case, again, there is no need to look ahead. Immediately after let comes the variable name, and only after parsing a : comes the variable type.
Therefore, the syntax of Rust is simply meant to avoid look ahead (Rust aims at having a LL(1) syntax) and the syntax of function arguments simply follows the regular syntax.
Oh, and by the way, not all arguments have a type:
impl Foo {
fn doit(&self);
}
x: typeis used by ML, and ML has influenced the design of Rust (as far as I know, the original rust compiler was written in OCaml).var: typesyntax goes back at least to Pascal.