Type inference

Now many of those examples don't look too nice, do they? For instance, why does Rust use this weird syntax for defining the type, why not just put it in front of the variable name, like C++ does? Also, most of that code looks pretty verbose, some types also look kind of complicated, do I really need to write all those? You don't, actually!

Of course, constants, function definitions and such still need to be typed. Apart from that, the compiler is able to infer the type of variables to a pretty large degree. Let's take the example code from the slice section from before and remove the unneeded type definitions.


#![allow(unused)]
fn main() {
let answer = 42; // Defaults to i32
// Reference to the variable
let my_reference = &answer;
println!("{}", answer);
println!("{}", *my_reference);
println!();

// Enough to infer type in all dependent variables
// Technically isn't needed because i32 works fine here
let my_array: [usize; 8] = [42; 8];
let other_array = [0, 1, 2, 3, 4, 5, 6, 7];
for number in my_array {
  print!("{} ", number);
}
println!();
println!();
for number in other_array {
  print!("{} ", number);
}
println!();
println!();

// Extra prints are hidden to make the code clearer
let element = my_array[3];
println!("{}", element); // 42
let element_reference = &my_array[3];
println!("{}", element_reference); // 42
let array_reference = &my_array;
// 42 42 42 42 42 42 42 42
for number in array_reference {
  print!("{} ", number);
}
println!();
let whole_array_slice = &other_array[..];
// 0 1 2 3 4 5 6 7
for number in whole_array_slice {
  print!("{} ", number);
}
println!();
// Sets everything to do with other_array to use usize
// Also could still just use the i32 default
let element_from_slice: usize = whole_array_slice[3];
println!("{}", element_from_slice); // 3
let another_whole_array = &other_array[0..8];
// 0 1 2 3 4 5 6 7
for number in another_whole_array {
  print!("{} ", number);
}
println!();
let array_front = &other_array[..=4];
// 0 1 2 3 4
for number in array_front {
  print!("{} ", number);
}
println!();
let array_back = &other_array[4..];
// 4 5 6 7
for number in array_back {
  print!("{} ", number);
}
println!();
let element_from_back = array_back[1];
println!("{}", element_from_back); // 5
}

This leads to small functions not having any type definition inside the function body, because everything can be inferred by the return type or the parameter types.

Literal types are mostly inferred by the type of the element they are assigned to. However, you can also provide a typed literal and let it infer its type into variables, instead.

let typed_variable: usize = 42;
let inferred_variable = 42_usize;