You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _posts/2025-10-16-elixir-v1-19-0-released.markdown
+1-41Lines changed: 1 addition & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
layout: post
3
-
title: "Elixir v1.19 released: enhanced type checking, broader type inference, and up to 4x faster compilation for large projects"
3
+
title: "Elixir v1.19 released: enhanced type checking and up to 4x faster compilation for large projects"
4
4
authors:
5
5
- José Valim
6
6
category: Releases
@@ -13,46 +13,6 @@ Elixir v1.19 brings further improvements to the type system and compilation time
13
13
14
14
This release improves the type system around two key areas: type inference and type checking of anonymous functions and protocols. These enhancements seem simple on the surface but required us to go beyond existing literature by extending current theory and developing new techniques. We will outline the technical details in future articles. For now, let's look at what's new.
15
15
16
-
### Type inference of all constructs
17
-
18
-
Type inference (or reconstruction) is the ability of a type system to automatically deduce, either partially or fully, the type of an expression at compile time. Type inference may occur at different levels. For example, many programming languages can automatically infer the types of variables, also known "local type inference", but not all can infer type signatures of functions.
19
-
20
-
Originally, our plan with Elixir's upcoming type system was to support type inference of patterns, guards, and return types. Therefore, if you wrote this simple function:
21
-
22
-
```elixir
23
-
defeven?(x) whenis_integer(x) do
24
-
rem(x, 2) ==0
25
-
end
26
-
```
27
-
28
-
Elixir would correctly infer the type to be `integer() -> boolean()`. However, if you wrote this function:
29
-
30
-
```elixir
31
-
defeven?(x) do
32
-
rem(x, 2) ==0
33
-
end
34
-
```
35
-
36
-
The type would be `dynamic() -> boolean()`, since there are no guards, even though the functions behave virtually the same, as the `rem` operator expects both arguments to be integer (they just raise different exceptions for non-integer values).
37
-
38
-
Inferring type signatures comes with a series of trade-offs:
39
-
40
-
* Speed - type inference algorithms are often more computationally intensive than type checking algorithms.
41
-
42
-
* Expressiveness - in any given type system, the constructs that support inference are always a subset of those that can be type-checked. Therefore, if a programming language is restricted to only fully reconstructed types, it is less expressive than a solely type checked counterpart.
43
-
44
-
* Incremental compilation - type inference complicates incremental compilation. If module A depends on module B, which depends on module C, a change to C may require the type signature in B to be reconstructed, which may then require A to be recomputed (and so on). This dependency chain may require large projects to explicitly add type signatures for stability and compilation efficiency.
45
-
46
-
* Cascading errors - when a user accidentally makes type errors or the code has conflicting assumptions, type inference may lead to less clear error messages as the type system tries to reconcile diverging type assumptions across code paths.
47
-
48
-
On the other hand, type inference offers the benefit of enabling type checking for functions and codebases without requiring the user to add type annotations. To balance these trade-offs, we are exploring "module type inference": our goal is to infer type signatures considering invocations of functions in the same module and of functions from *other applications* (such as Elixir itself and your dependencies). Once module types are inferred, your whole project is type checked considering all declared and inferred types.
49
-
50
-
We have successfully implemented these features as part of Elixir v1.19, by performing inference of all constructs (except guards), taking into account the signatures from calls to functions within the same module and in Elixir's standard library. This means the second function above, without the guard, will also infer the type `integer() -> boolean()`.
51
-
52
-
In future releases, we plan to perform type inference of guards (originally planned for v1.19) and also consider the type signatures of your dependencies during inference. Overall, these changes allow us to assess the impact of the trade-offs above as the type system evolves, which suits well our current goals of incrementally using types to find bugs in existing codebases, without changing them.
53
-
54
-
Keep in mind this only applies to *type inference*. Once we introduce type signatures and you explicitly annotate your functions, type inference and the trade-offs above no longer play a role. Any function with an explicit type signature will be typed checked against the user-provided annotations, as in other statically typed languages.
55
-
56
16
### Type checking of protocol dispatch and implementations
57
17
58
18
This release adds type checking when dispatching and implementing protocols.
0 commit comments