On the other hand: Can I specify the type explicitely? This doesn't seem to compile:
let mut vec = Vec<u32>::new();
The use of <> to specify generic arguments is ambiguous in an expression context where < could be the "less than" operator.
Thus, whenever you want to specify generic parameters explicitly in an expression context, you need to use the so-called "turbofish" operator to disambiguate:
let mut vec = Vec::<u32>::new();
This way the distinction is purely syntactic.
How does new() know what is requested vector element type when (unlike C++) it is not parametrized with type name?
The term you are looking for is type inference: the ability of the compiler to infer the type from the context, without it being explicitly specified.
Different languages have different type inference algorithms:
- C++ has one-way type inference: the type of an expression can be inferred without specifying it, allowing the use of
auto to declare a variable.
- Java has one-way type inference in the other direction for generics:
HashMap<String, String> map = new HashMap<>();.
- Rust has two-way type inference, as it uses a variant of Hindley-Milner, making it so that you rarely have to specify the type within a function body.
For illustrative purpose, imagine the following (Playground link):
fn display(i: u64) {
println!("{}", i);
}
fn main() {
let mut vec = Vec::new();
vec.push(1);
display(vec[0]);
}
The compiler will reason in the following way:
vec has type Vec<?0>.
Vec<?0>::push takes an {integer} as argument, hence ?0 is an {integer}.
<Vec<?0> as Index>::Output is ?0.
display takes a u64 as argument, thus ?0 is u64.
This combination of links (threading ?0 through) allows it to gather 2 constraints:
?0 is an {integer}.
?0 is u64.
Since both constraints are satisfied by ?0 being a u64, then it is inferred to be a u64.
If however you change display to take a &str, then you'll get an error message as inference will fail:
error[E0308]: mismatched types
--> src/main.rs:10:17
|
10 | display(vec[0]);
| ^^^^^^ expected `&str`, found integer
Because satisfying ?0 = &str and ?0 is {integer} at the same time is impossible.