# Elixir changelog > A dynamic, functional language for scalable applications. - Vendor: Elixir - Category: Languages & Runtimes - Official site: https://elixir-lang.org - Tracked by: What's New (https://whatsnew.fyi/product/elixir) - Harvested from: GitHub (elixir-lang/elixir) - Entries below: 9 (newest first) What's New is an index, not a publisher: every entry below links to the vendor's own release notes, which are the authoritative source. Entries are labelled where they are hand-curated sample data, pre-releases, or drawn from a secondary source such as a developer blog. ## Releases ### v1.20.3 - Date: 2026-08-04 - Version: v1.20.3 - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.3 - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20.3 - **changed** — Batch type checker cache operations in Kernel.ParallelCompiler to improve compilation times - **fixed** — Improve type precision of the ++/2 operator - **fixed** — Improve type precision of the send/2 return type - **fixed** — Improve type refinement for and/2 and or/2 - **fixed** — Fix type checking of Map.put/3 on empty map types - **fixed** — Fix type checking of tuple insertion on equivalent tuple types - **fixed** — Fix type checking of tuple insertion on gradual types with empty static parts - **fixed** — Fix variable refinements leaking from invalid receive/after timeout expressions - **fixed** — Fix rendering inferred types containing unions of static and dynamic functions - **fixed** — Ensure typing errors in :maps.values/1 reference the correct function - **fixed** — Mark %_{} patterns as precise so subsequent redundant struct clauses are detected - **fixed** — Fix parsing of the --profile time option in elixirc - **fixed** — Fix break!/1 in IEx.Helpers with unknown expressions ###### 1. Enhancements ###### Elixir * [Kernel.ParallelCompiler] Batch type checker cache operations to improve compilation times ###### 2. Bug fixes ###### Elixir * [Kernel] Improve type precision of the `++/2` operator * [Kernel] Improve type precision of the `send/2` return type * [Kernel] Improve type refinement for `and/2` and `or/2` * [Kernel] Fix type checking of `Map.put/3` on empty map types * [Kernel] Fix type checking of tuple insertion on equivalent tuple types * [Kernel] Fix type checking of tuple insertion on gradual types with empty static parts * [Kernel] Fix variable refinements leaking from invalid `receive/after` timeout expressions * [Kernel] Fix rendering inferred types containing unions of static and dynamic functions * [Kernel] Ensure typing errors in `:maps.values/1` reference the correct function * [Kernel] Mark `%_{}` patterns as precise so subsequent redundant struct clauses are detected * [elixirc] Fix parsing of the `--profile time` option ###### IEx * [IEx.Helpers] Fix `break!/1` with unknown expressions ### v1.20.2 - Date: 2026-06-23 - Version: v1.20.2 - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.2 - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20.2 - **added** — Include per-module type checking times when compiler profiling is enabled with profile: :time - **fixed** — Fix binary comprehensions with sizes when options such as :uniq or :into are used - **fixed** — Improve compiler error messages when quote with unquote is used inside a pattern or guard - **fixed** — Restore the compiler optimization of Kernel.put_elem/3 to emit :erlang.setelement/3 - **fixed** — Fix type checking when applying an empty function type - **fixed** — Fix type checking of bitstring patterns that reuse variables - **fixed** — Fix type information for __info__(:struct) to include the :required key - **fixed** — Fix type operations on map and optional keys during difference/intersection, including open keys and empty intersections - **fixed** — Fix typing of list types involving dynamic or empty lists - **fixed** — Include bitstrings as a possible domain key in the type system - **fixed** — Preserve file metadata from each clause in type system warnings - **fixed** — Fix type warnings for protocol implementations whose protocol module defines additional callbacks - **fixed** — Raise clearer type checking errors when an expected struct is removed or redefined during compilation - **fixed** — Avoid unnecessary umbrella recompilation when a path dependency's manifest is newer but unchanged - **fixed** — Recompile fetched dependencies when their compile-time environment changes ###### 1. Enhancements ###### Elixir * [Kernel.ParallelCompiler] Include per-module type checking times when compiler profiling is enabled with `profile: :time` ###### 2. Bug fixes ###### Elixir * [Kernel] Fix binary comprehensions with sizes when options such as `:uniq` or `:into` are used * [Kernel] Improve compiler error messages when `quote` with `unquote` is used inside a pattern or guard * [Kernel] Restore the compiler optimization of `Kernel.put_elem/3` to emit `:erlang.setelement/3` * [Module] Fix type checking when applying an empty function type * [Module] Fix type checking of bitstring patterns that reuse variables * [Module] Fix type information for `__info__(:struct)` to include the `:required` key * [Module] Fix type operations on map and optional keys during difference/intersection, including open keys and empty intersections * [Module] Fix typing of list types involving dynamic or empty lists * [Module] Include bitstrings as a possible domain key in the type system * [Module] Preserve file metadata from each clause in type system warnings * [Module] Fix type warnings for protocol implementations whose protocol module defines additional callbacks * [Module] Raise clearer type checking errors when an expected struct is removed or redefined during compilation ###### Mix * [mix compile] Avoid unnecessary umbrella recompilation when a path dependency's manifest is newer but unchanged * [mix deps.compile] Recompile fetched dependencies when their compile-time environment changes ### v1.20.1 - Date: 2026-06-09 - Version: v1.20.1 - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.1 - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20.1 - **security** — Limit integer components in Version to 14 decimal bytes to avoid parsing too large integers from untrusted user input - **fixed** — Cap width in Calendar.strftime/2 to 1024 characters - **fixed** — Ensure Code.require_file releases the file if compilation fails - **fixed** — Fix documentation generation to use the correct version in search - **fixed** — Validate paths and files when extracting archives in mix archive.install - **fixed** — Honor --no-compile option when loading plugins in mix format ###### 1. Security ###### Elixir * [Version] Limit integer components in Version to 14 decimal bytes, to avoid parsing too large integers from untrusted user input. We strongly advise developers parsing versions from user input to limit the data size given to the `Version` module (CVE-2026-49762, GHSA-w2h8-8x3g-278p) ###### 2. Bug fixes ###### Elixir * [Calendar] Cap width in `Calendar.strftime/2` to 1024 characters * [Code] Ensure `Code.require_file` releases the file if compilation fails * [Kernel] Fix documentation generation to use the correct version in search ###### Mix * [mix archive.install] Validate paths and files when extracting archives * [mix format] Honor `--no-compile` option when loading plugins ### v1.20.0 - Date: 2026-06-03 - Version: v1.20.0 - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.0 - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20.0 - **added** — Type inference system that infers types for function definitions using typing information from standard library and dependencies to find verified bugs and dead code - **added** — Type inference of guards including support for is_list, is_integer, is_binary, is_map_key, tuple_size and other guard expressions - **added** — Whole-body type inference based on function bodies to infer expected argument types and return types - **added** — Type refinement across clauses using occurrence typing for case, cond, and with expressions - **added** — Typing of map keys with support for both atom keys and domain keys including integer and float types - **added** — Typing of map operations in the Map module to track how keys are added, updated, and removed - **added** — Type system support for if_set and not_set type modifiers to track conditional key existence in maps - **changed** — Minimum required Erlang/OTP version is now 27 or higher Announcement: https://elixir-lang.org/blog/2026/06/03/elixir-v1-20-0-released/ This release requires Erlang/OTP 27+ and is compatible with Erlang/OTP 29. ##### Type system improvements Elixir's type system now understands all language constructs and can infer types for your function definitions, using typing information from Elixir's standard library and your dependencies, to find verified bugs and dead code. This has been achieved through a series of improvements, such as type refinement across clauses, occurrence typing, typing of map keys and domains, and more. ###### Type inference of guards This release also performs inference of guards! Let's see some examples: ```elixir def example(x, y) when is_list(x) and is_integer(y) ``` The code above correctly infers `x` is a list and `y` is an integer. ```elixir def example({:ok, x} = y) when is_binary(x) or is_integer(x) ``` The one above infers x is a binary or an integer, and `y` is a two element tuple with `:ok` as first element and a binary or integer as second. ```elixir def example(x) when is_map_key(x, :foo) ``` The code above infers `x` is a map which has the `:foo` key, represented as `%{..., foo: dynamic()}`. Remember the leading `...` indicates the map may have other keys. ```elixir def example(x) when not is_map_key(x, :foo) ``` And the code above infers `x` does not have the `:foo` key (hence `x.foo` will raise a typing violation), which has the type: `%{..., foo: not_set()}`. You can also have expressions that assert on the size of data structures: ```elixir def example(x) when tuple_size(x) < 3 ``` Elixir will correctly track the tuple has at most two elements, and therefore accessing `elem(x, 3)` will emit a typing violation. In other words, Elixir can look at complex guards, infer types, and use this information to find bugs in our code, without a need to introduce type signatures (yet). ###### Whole-body type inference Elixir also performs inference based on the function body itself. Take the following code: ```elixir def add_foo_and_bar(data) do data.foo + data.bar end ``` Elixir now infers that the function expects a `map` as first argument, and the map must have the keys `.foo` and `.bar` whose values are either `integer()` or `float()`. The return type will be either `integer()` or `float()`. Here is another example: ```elixir def sum_to_string(a, b) do Integer.to_string(a + b) end ``` Even though the `+` operator works with both integers and floats, Elixir infers that `a` and `b` must be both integers, as the result of `+` is given to a function that expects an integer. The inferred type information is then used during type checking to find possible typing errors. The typing inferred from your dependencies are also used to help infer more precise types for your own applications. ###### Typing across clauses Elixir now infers the type of a given clause based on previous clauses. Let's see an example: ```elixir case System.get_env("SOME_VAR") do nil -> :not_found value -> {:ok, String.upcase(value)} end ``` `System.get_env("SOME_VAR")` returns either `nil` or a `binary()`. Because the first clause matches on `nil`, the type system knows `value` can no longer be `nil`, and therefore it must only be a `binary()`, which allows the second clause to also type check without violations. This type inference across clauses also helps the type system find redundant clauses and dead code in existing codebases. Elixir v1.20 also implements occurrence typing for `cond`, `case`, and `with`, providing more precise types within each clause. ###### Typing of atom and domain keys in maps Maps were one of the first data-structures we implemented within the Elixir type system however, up to this point, they only supported atom keys. If they had additional keys, those keys were simply marked as `dynamic()`. As of Elixir v1.20, we can track all possible d _[Truncated at 4000 characters — full notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.0]_ ### v1.20.0-rc.6 - Date: 2026-05-21 - Version: v1.20.0-rc.6 - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.0-rc.6 - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20.0-rc.6 - Labels: Pre-release - **added** — Perform type inference across applications - **fixed** — Fix type checker bug when validating a case inside a cond condition - **fixed** — Preserve evaluation order when rewriting function calls from Elixir modules into Erlang ones - **fixed** — Do not show dependency as diverged when it actually requires compilation - **fixed** — Respect --raise when mix test --warnings-as-errors passes with warnings - **deprecated** — xref: [exclude: ...] in mix.exs is deprecated in favor of elixirc_options: [no_warn_undefined: ...] This release requires Erlang/OTP 27+ and is compatible with Erlang/OTP 29. ###### 1. Enhancements ###### Elixir * [Kernel] Perform type inference across applications ###### 2. Bug fixes ###### Elixir * [Kernel] Fix type checker bug when validating a `case` inside a `cond` condition (regression) * [Kernel] Preserve evaluation order when rewriting function calls from Elixir modules into Erlang ones ###### Mix * [mix deps] Do not show dependency as diverged when it actually requires compilation (regression) * [mix deps] Revert allowing overriding specific dependencies in `:override` due to conflicts with Hex (revert) * [mix test] Respect --raise when mix test --warnings-as-errors passes with warnings ###### 3. Hard deprecations ###### Mix * [mix compile.elixir] `xref: [exclude: ...]` in your `mix.exs` is deprecated in favor of `elixirc_options: [no_warn_undefined: ...]` ### v1.20-latest - Date: 2026-05-21 - Version: v1.20-latest - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20-latest - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20-latest Automated release for latest v1.20. ### v1.20.0-rc.5 - Date: 2026-05-13 - Version: v1.20.0-rc.5 - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.0-rc.5 - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20.0-rc.5 - Labels: Pre-release - **added** — Add occurrence typing on `case`, `cond`, and `with` - **added** — Add `source/1` to IEx.Helpers - **added** — Add `mix source MODULE` to print or open a given module/function location - **changed** — Optimize Base validation functions by using SWAR techniques - **changed** — Optimize `Float.round/2` by avoiding big integers - **changed** — Increase inspect limit to help print deeply nested data structures - **changed** — Support printing Erlang records using Erlang notation - **changed** — Switch Registry `{:duplicate, :key}` key_ets to ordered_set with composite keys - **changed** — SWAR-optimize ASCII fast paths in `String.length/1` and `String.slice/3` - **changed** — Show remaining runs when using `--repeat-until-failure` - **changed** — Support `--output` option in `mix app.tree` - **changed** — Support `--output` option in `mix deps.tree` - **changed** — Support printing docs for types and callbacks in `mix help` - **changed** — Support `--no-compile` option in `mix format` - **changed** — Optimize EEx compiler by flattening expr list only once - **fixed** — Fix a compiler crash when importing a module with `only: :sigils` option when the imported module exports non-sigil symbols with `sigil_` prefix - **fixed** — Reject negative Duration in `to_timeout/1` - **fixed** — Fix generation of heredocs in `Macro.to_string/1` with escaped trailing newline - **fixed** — Consistently return path as binary in `Path.relative_to_cwd/2` - **fixed** — Raise in `Stream.cycle/1` when enumerable reduce call yields no elements This release requires Erlang/OTP 27+ and is compatible with Erlang/OTP 29. ###### 1. Enhancements ###### EEx * [EEx] Optimize compiler by flattening expr list only once ###### Elixir * [Base] Optimize Base validation functions by using SWAR techniques * [Float] Optimize `Float.round/2` by avoiding big integers * [Inspect] Increase inspect limit to help print deeply nested data structures * [Inspect] Support printing Erlang records (using Erlang notation) * [Kernel] Add occurrence typing on `case`, `cond`, and `with` * [Registry] Switch `{:duplicate, :key}` key_ets to ordered_set with composite keys * [String] SWAR-optimize ASCII fast paths in `String.length/1` and `String.slice/3` ###### ExUnit * [ExUnit] Show remaining runs when using `--repeat-until-failure` ###### IEx * [IEx.Helpers] Add `source/1` ###### Mix * [mix app.tree] Support `--output` option * [mix deps.tree] Support `--output` option * [mix help] Support printing docs for types and callbacks * [mix format] Support `--no-compile` option * [mix source] Add `mix source MODULE` to print or open a given module/function location ###### 2. Potential breaking changes ###### Elixir * [Kernel] Disallow raw CR line ending in strings, comments and after `?` for security reasons ###### 3. Bug fixes ###### Elixir * [Kernel] Fix a compiler crash when importing a module with `only: :sigils` option when the imported module exports non-sigil symbols with `sigil_` prefix * [Kernel] Reject negative Duration in `to_timeout/1` * [Macro] Fix generation of heredocs in `Macro.to_string/1` with escaped trailing newline * [Path] Consistently return path as binary in `Path.relative_to_cwd/2` * [Stream] Raise in `Stream.cycle/1` when enumerable reduce call yields no elements * [String] Support empty pattern list in `String.count/2` ###### Logger * [Logger] Persist log level to app env in `Logger.configure/1` ###### Mix * [Mix] Use `non_executable_binary_to_term` on loopback pubsub * [mix compile.elixir] Fix scenario where Elixir would tag mtimes in the future ### v1.20.0-rc.4 - Date: 2026-03-31 - Version: v1.20.0-rc.4 - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.20.0-rc.4 - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.20.0-rc.4 - Labels: Pre-release - **added** — Add `:dbg_callback` option to eval functions in Code - **added** — Allow preserving sigil metadata in `Code.Fragment.container_cursor_to_quoted` - **added** — Add support for `[:raw]` opts in `File.read/2` - **added** — Show undefined function errors even when missing variables to help debug errors caused when the developer forgets to require a macro - **added** — Add `Process.get_label/1` - **added** — Allow overriding specific dependencies in `:override` in mix deps - **changed** — Purge and delete modules if `after_verify/2` callback fails - **changed** — Support via tuples in `PartitionSupervisor.count_children/1` and `stop/3` - **fixed** — Fix `Integer.extended_gcd/2` returning negative GCD for zero base cases - **fixed** — Raise when negative out-of-range digits are given to `Integer.undigits/2` - **fixed** — Protocols should not add compile-time dependencies on `Any` implementation - **fixed** — Ensure structs trigger recompilation for type checking purposes - **fixed** — Ensure type information propagate across `hd/tl` in guards - **fixed** — Raise `ArgumentError` in `Keyword.from_keys/2` for non-atom keys - **fixed** — Fix `URI.merge` leaking `:+` marker when base path is empty string - **fixed** — Avoid false positives when diffing bitstrings in ExUnit.Diff - **fixed** — Use config files to pass project state to avoid argv limits on Windows when using `MIX_OS_DEPS_COMPILE_PARTITION_COUNT` - **fixed** — Fix compile env change triggering full recompilation of path dependencies - **fixed** — Add a build lock around protocol consolidation in umbrellas - **fixed** — Ensure compilation of sibling deps do not mark path deps as changed This release requires Erlang/OTP 27+ and is compatible with Erlang/OTP 29. ###### 1. Enhancements ###### Elixir * [Code] Add `:dbg_callback` option to eval functions * [Code.Fragment] Allow preserving sigil metadata in `container_cursor_to_quoted` * [File] Add support for `[:raw]` opts in `File.read/2` * [Kernel] Show undefined function errors even when missing variables (this helps debug errors caused when the developer forgets to require a macro) * [Module] Purge and delete modules if `after_verify/2` callback fails * [PartitionSupervisor] Support via tuples in `count_children/1` and `stop/3` * [Process] Add `Process.get_label/1` ###### Mix * [mix deps] Allow overriding specific dependencies in `:override` ###### 2. Bug fixes ###### Elixir * [Integer] Fix `Integer.extended_gcd/2` returning negative GCD for zero base cases * [Integer] Raise when negative out-of-range digits are given to `Integer.undigits/2` * [Kernel] Protocols should not add compile-time dependencies on `Any` implementation * [Kernel] Ensure structs trigger recompilation for type checking purposes (regression) * [Kernel] Ensure type information propagate across `hd/tl` in guards (regression) * [Keyword] Raise `ArgumentError` in `Keyword.from_keys/2` for non-atom keys * [URI] Fix `URI.merge` leaking `:+` marker when base path is empty string ###### ExUnit * [ExUnit.Diff] Avoid false positives when diffing bitstrings ###### Mix * [mix deps] Use config files to pass project state to avoid argv limits on Windows when using `MIX_OS_DEPS_COMPILE_PARTITION_COUNT` * [mix compile] Fix compile env change triggering full recompilation of path dependencies * [mix compile] Add a build lock around protocol consolidation in umbrellas * [mix compile] Ensure compilation of sibling deps do not mark path deps as changed * [mix test] Fix `--warnings-as-errors` not catching misnamed test file warnings ### v1.18-latest - Date: 2024-12-10 - Version: v1.18-latest - Original notes: https://github.com/elixir-lang/elixir/releases/tag/v1.18-latest - Permalink: https://whatsnew.fyi/product/elixir/releases/v1.18-latest Automated release for latest v1.18.