> For the complete documentation index, see [llms.txt](https://harmeetsingh.gitbook.io/scala-type-system/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://harmeetsingh.gitbook.io/scala-type-system/phase-i/chapter-4-type-inference.md).

# Chapter 4: Type Inference

Type inference is one of the most powerful features of modern programming languages. It is supported by both **statically typed** and **dynamically typed** languages, although the mechanism differs between them.

In dynamically typed languages, the runtime (interpreter or virtual machine) determines the types of values as the program executes. In statically typed languages, the compiler analyzes expressions during compilation and automatically infers their types. The sophistication of type inference varies from language to language.

Scala has one of the richest type inference systems among mainstream programming languages. The compiler can infer types in many situations, including:

* Variable declarations
* Method return types
* Generic type parameters
* Pattern matching
* Anonymous functions
* And many other language constructs

Compared to Scala, Java provides more limited type inference. Java 7 introduced the **diamond operator (`<>`)** for inferring generic types, Java 8 improved type inference in lambda expressions, and Java 10 introduced the `var` keyword for local variable type inference. However, Scala's type inference remains significantly more expressive.

Consider the following example:

```scala
val name = “Harmeet”
```

When the Scala compiler encounters this declaration, it first checks whether an explicit type annotation has been provided.

* If a type annotation is present, the compiler verifies that the expression conforms to the declared type.
* Otherwise, it evaluates the expression and infers the variable's type from the expression's result.

The compiler follows the same general approach when inferring method return types, pattern matching expressions, and many other constructs.

Suppose an expression can produce values of different types, as in the following examples:<br>

```scala
val result = if(<condition>) 13 else “thirteen”

val result = obj match {
	case value: String => value
	case value: Int => value
}
```

In these cases, the compiler searches for the **least upper bound (LUB)**—that is, the most specific type that is a supertype of all possible result types.

To determine the inferred type, Scala consults its type hierarchy (which we will explore in the next chapter):

```scala
Int => AnyVal => Any
String => AnyRef => Any
```

Since `Int` and `String` have only one common supertype, `Any`, the inferred type of `result` is:

```
val result: Any = ...
```

This is why the compiler infers `Any` as the type of `result`.

#### Some Internals:&#x20;

As we know, Scala source code is compiled into JVM bytecode. Since the JVM is based on Java, an obvious question arises:

> **How does Scala represent the `Any` type in JVM bytecode, given that Java has no `Any` type?**

Consider the following example:

```scala
val answer = if(<condition>) 13 else “thirteen”
```

At the Scala language level, the inferred type is `Any`.

However, on the JVM, `Any` is represented differently depending on the values involved. Primitive values such as `Int` are **boxed** into their corresponding Java wrapper classes when necessary.

In this example:

* `Int` is boxed to `java.lang.Integer`.
* `"thirteen"` is already a `java.lang.String`.
* Both `Integer` and `String` inherit from `java.lang.Object`.

Therefore, after boxing, the common JVM type becomes `Object`.

A simplified version of the generated bytecode looks similar to the following:

```java
public Object method() {
        return BoxesRunTime.boxToInteger(12);
}
```

Although Scala exposes `Any` at the language level, the generated JVM bytecode ultimately works with `java.lang.Object` whenever a common reference type is required.
