Hacker News new | ask | show | jobs
by trealira 917 days ago
I guess you're right. I think of type inference as "there is no pre-set type for a literal; the type is is inferred based on the context it's used in." But that isn't the definition of type inference. The definition is just that its type can be deduced at compile-time without explicit annotation. But that means that, as long as you don't have to do explicit casting for every expression (e.g. "(5i32 + 6i32) as i32"), all expressions are type-inferred no matter what programming language you're in.

Like, in Rust, the type of a literal depends on the context of the variable it's later used as.

  // Due to usage below first line,
  // 5 is retroactively reanalyzed as if it were 5u8
  let a = 5;
  let b: u8 = a + 1;
Whereas in C, literals always have a set type, and the only reason you can use, e.g., int literals in non-integer expressions is due to the great amount of implicit type conversions in C.

C++, which has a form of type inference, works differently: the type of a variable is always the same as the type of expression initializing it. The closest equivalent in C++:

  // "a" is inferred to be an "int" because 5 is always of type "int" 
  auto a = 5;
  uint8_t b = a + 1; // Implicit truncation from "int" to "uint8_t"
There true equivalent of an integer literal 5 from C (on 64-bit Linux) in Rust would be 5i32, because it's always the same sign, type, and size in every expression. There's never any doubt about the type of an expression or a literal, and hence no need for some type inference algorithm, only implicit conversions. Hence, the equivalent in Rust of the above C++ is this (depending on the platform):

  let a = 5i32;
  let b: u8 = (a + 1i32) as u8;