21

Rust performs type inference in fairly advanced situations. Could someone please explain (or point to) the rules that describe what can and cannot be inferred?

The first one is simple: The type of a binding is the type of the bound expression:

let n = 10u32;

// Same as:
//   vvvvv
let n: u32 = 10u32;

This next one is more surprising to me: The generic parameter on the right is deduced from the binding type on the left:

let n: u32 = "10".parse().unwrap();

// same as:            vvvvvvv
let n: u32 = "10".parse::<u32>().unwrap();

This also works for "member functions" of generic types:

let b = Box::new(10u32);

// same as:
//        vvvvv      vvvvvvv
let b: Box<u32> = Box::<u32>::new(10u32);

But the strangest of all is type inference across statements:

let v = Vec::new();   // no type!
v.push(10u32);        // apparently v is Vec<u32>?!
// v.push(10i32);     // type error

What are the rules for type inference and type deduction?

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • It is based on [Hindler-Milner](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system). The implementation is explained in https://github.com/rust-lang/rust/blob/master/src/librustc/infer/README.md but it is pretty outdated (still using pre-1.0 syntax). – kennytm May 31 '16 at 10:53
  • @kennytm: HM doesn't have a notion of "statement", does it? How does that explain something like `vec!`? – Kerrek SB May 31 '16 at 10:56
  • HM does have `let x = e₁ in e₂`. – kennytm May 31 '16 at 10:59
  • @KerrekSB: I always thought of it as basically a constraint-solver (with some `Deref` bonuses thrown in); I am afraid that attempting to pin-point it more is likely to become outdated in the future. – Matthieu M. May 31 '16 at 11:23
  • @MatthieuM.: Yeah, I can see that it works in practice as long in a way that it tries to figure out the only type assignments that make sense, but I couldn't find a systematic treatment anywhere. Code like `Box::new(5)` is everywhere, but it's never stated anywhere why that works. – Kerrek SB May 31 '16 at 11:33

1 Answers1

12

Rust uses Hindley-Milner type system. It is a set of rules about establishing types of expressions based on their usage.

Formal description and explanation for it can be found there:

"What part of Hindley-Milner do you not understand?"

mcarton
  • 27,633
  • 5
  • 85
  • 95
Hauleth
  • 22,873
  • 4
  • 61
  • 112