Releases: elixir-lang/elixir
v1.19.0-rc.2
1. Enhancements
Elixir
- [Regex] Raise error message when regexes are used as default values in struct fields for compatibility with Erlang/OTP 28
- [Registry] Add key-based partitioning of duplicate registries
2. Bug fixes
Elixir
- [Kernel] Address issue with type checking not completing on protocol consolidation
ExUnit
- [ExUnit] Do not crash on empty test unit groups
Mix
- [mix help] Add
mix help app:APP
- [mix test] Fix module preloading in
mix test --slowest-modules=N
v1.19-latest
Automated release for latest v1.19.
main-latest
Automated release for latest main.
v1.19.0-rc.1
1. Enhancements
Elixir
- [Kernel] Raise when U+2028 and U+2029 characters are present in comments and strings to avoid line spoofing attacks
- [Kernel] Include the line for the previous clause in errors/warnings related to conflicts between defaults on function definitions
- [Macro] Add
__escape__/1
callback so structs can escape references and other runtime data types inMacro.escape/1
- [OptionParser] Support the
:regex
type - [OptionParser] Enhance parsing error to display available options
- [String] Update to Unicode 17.0.0
ExUnit
- [ExUnit] Set a process label for each test
Logger
- [Logger] Accept any enumerable in
Logger.metadata/1
Mix
- [mix format] Add options to mix format to allow excluding of files
- [mix test] Add
--name-pattern
option tomix test
- [Mix.install/2] Support the
:compilers
option
2. Bug fixes
Elixir
- [Code] Return error on invalid unicode sequences in
Code.string_to_quoted/2
instead of raising - [Code] Properly handle column annotation for
in
innot in
expressions - [Enum] Fix infinite loop on
Enum.take/2
with negative index on empty enumerable - [Inspect] Inspect ill-formed structs as maps
- [Kernel] Properly increment metadata newline when
?
is followed by a literal newline character
ExUnit
- [ExUnit.Assertions] Fix order in ExUnit results when listing pinned variables
- [ExUnit.Assertions] Raise if attempting to raise an assertion error with invalid message (not a binary)
IEx
- [IEx] Abort pipelines when there is an error in any step along the way
Mix
- [mix compile] Fix bug where reverting changes to an external resource (such as HEEx template) after a compilation error would make it so the source module would not be compiled
- [mix compile] Avoid failures when locking compilation across different users
- [mix compile] Fix race condition when renaming files used by the compilation lock
- [mix test] Prevent
mix test
from overriding:failures_manifest_path
option
3. Hard deprecations
Elixir
- [Code] Warn if line-break characters outside of
\r
and\r\n
are found in strings according to UX#55. This warning will be fast-tracked into an error for security reasons in Elixir v1.20, following a similar rule to bidirectional control characters. They will already raise if found in comments
v1.18-latest
Automated release for latest v1.18.
v1.19.0-rc.0
Type system improvements
Type checking of protocol dispatch and implementations
This release also adds type checking when dispatching and implementing protocols.
For example, string interpolation in Elixir uses the String.Chars
protocol. If you pass a value that does not implement said protocol, Elixir will now emit a warning accordingly.
Here is an example passing a range, which cannot be converted into a string, to an interpolation:
defmodule Example do def my_code(first..last//step = range) do "hello #{range}" end end
the above emits the following warnings:
warning: incompatible value given to string interpolation: data it has type: %Range{first: term(), last: term(), step: term()} but expected a type that implements the String.Chars protocol, it must be one of: dynamic( %Date{} or %DateTime{} or %NaiveDateTime{} or %Time{} or %URI{} or %Version{} or %Version.Requirement{} ) or atom() or binary() or float() or integer() or list(term())
Warnings are also emitted if you pass a data type that does not implement the Enumerable
protocol as a generator to for-comprehensions:
defmodule Example do def my_code(%Date{} = date) do for(x <- date, do: x) end end
will emit:
warning: incompatible value given to for-comprehension: x <- date it has type: %Date{year: term(), month: term(), day: term(), calendar: term()} but expected a type that implements the Enumerable protocol, it must be one of: dynamic( %Date.Range{} or %File.Stream{} or %GenEvent.Stream{} or %HashDict{} or %HashSet{} or %IO.Stream{} or %MapSet{} or %Range{} or %Stream{} ) or fun() or list(term()) or non_struct_map()
Type checking and inference of anonymous functions
Elixir v1.19 can now type infer and type check anonymous functions. Here is a trivial example:
defmodule Example do def run do fun = fn %{} -> :map end fun.("hello") end end
The example above has an obvious typing violation, as the anonymous function expects a map but a string is given. With Elixir v1.19, the following warning is now printed:
warning: incompatible types given on function application: fun.("hello") given types: binary() but function has type: (dynamic(map()) -> :map) typing violation found at: │ 6 │ fun.("hello") │ ~ │ └─ mod.exs:6:8: Example.run/0
Function captures, such as &String.to_integer/1
, will also propagate the type as of Elixir v1.19, arising more opportunity for Elixir's type system to catch bugs in our programs.
Acknowledgements
The type system was made possible thanks to a partnership between CNRS and Remote. The development work is currently sponsored by Fresha, Starfish*, and Dashbit.
Faster compile times in large projects
This release includes two compiler improvements that can lead up to 4x faster builds in large codebases.
While Elixir has always compiled the given files in project or a dependency in parallel, the compiler would sometimes be unable to use all of the machine resources efficiently. This release addresses two common limitations, delivering performance improvements that scale with codebase size and available CPU cores.
Code loading bottlenecks
Prior to this release, Elixir would load modules as soon as they were defined. However, because the Erlang part of code loading happens within a single process (the code server), this would make it a bottleneck, reducing the amount of parallelization, especially on large projects.
This release makes it so modules are loaded lazily. This reduces the pressure on the code server, making compilation up to 2x faster for large projects, and also reduces the overall amount of work done during compilation.
Implementation wise, the parallel compiler already acts as a mechanism to resolve modules during compilation, so we built on that. By making sure the compiler controls both module compilation and module loading, it can also better guarantee deterministic builds.
The only potential regression in this approach happens if you have a module, which is used at compile time and defines an @on_load
callback (typically used for NIFs) that invokes another modules within the same project. For example:
defmodule MyLib.SomeModule do @on_load :init def init do MyLib.AnotherModule.do_something() end def something_else do ... end end MyLib.SomeModule.something_else()
The reason this fails is because @on_load
callbacks are invoked within the code server and therefore they have limited ability to load additional modules. It is generally advisable to limit invocation of external modules during @on_load
callbacks but, in case it is strictly necessary, you can set @compile {:autoload, true}
in the invoked module to address this issue in a forward and backwards compatible manner.
Parallel compilation of dependencies
This release introduces a variable called MIX_OS_DEPS_COMPILE_PARTITION_COUNT
, which instructs mix deps.compile
to compile dependencies in parallel.
While fetching dependencies and compiling individual Elixir dependencies already happened in parallel, there were pathological cases where performance would be left on the table, such as compiling dependencies with native code or dependencies where one or two large file would take over most of the compilation time.
By setting MIX_OS_DEPS_COMPILE_PARTITION_COUNT
to a number greater than 1, Mix will now compile multiple dependencies at the same time, using separate OS processes. Empirical testing shows that setting it to half of the number of cores on your machine is enough to maximize resource usage. The exact speed up will depend on the number of dependencies and the number of machine cores, although some reports mention up to 4x faster compilation times. If you plan to enable it on CI or build servers, keep in mind it will most likely have a direct impact on memory usage too.
Improved pretty printing algorithm
Elixir v1.19 ships with a new pretty printing implementation that tracks limits as a whole, instead of per depth. Previous versions would track limits per depth. For example, if you had a list of lists of 4 elements and a limit of 5, it would be pretty printed as follows:
[ [1, 2, 3], [1, 2, ...], [1, ...], [...], ... ]
This allows for more information to be shown at different nesting levels, which is useful for complex data structures. But it led to some pathological cases where the limit
option had little effect on actually filtering the amount of data shown. The new implementation decouples the limit handling from depth, decreasing it as it goes. Therefore, the list above with the same limit in Elixir v1.19 is now printed as:
[ [1, 2, 3], ... ]
The outer list is the first element, the first nested list is the second, followed by three numbers, reaching the limit. This gives developers more precise control over pretty printing.
Given this may reduce the amount of data printed by default, the default limit has also been increased from 50 to 100. We may further increase it in upcoming releases based on community feedback.
OpenChain certification
Elixir v1.19 is also our first release following OpenChain compliance, as previously announced. In a nutshell:
- Elixir releases now include a Source SBoM in CycloneDX 1.6 or later and SPDX 2.3 or later formats.
- Each release is attested along with the Source SBoM.
These additions offer greater transparency into the components and licenses of each release, supporting more rigorous supply chain requirements.
This work was performed by Jonatan Männchen and sponsored by the Erlang Ecosystem Foundation.
v1.19.0-rc.0 (2025-06-09)
1. Enhancements
Elixir
- [Access] Add
Access.values/0
for traversing maps and keyword lists values - [Base] Add functions to verify if an encoding is valid, such as
valid16?
,valid64?
, and so forth - [Calendar] Support 2-arity options for
Calendar.strftime/3
which receives the whole data type - [Code] Add
:migrate_call_parens_on_pipe
formatter option - [Code] Add
:indentation
option toCode.string_to_quoted/2
- [Code.Fragment] Preserve more block content around cursor in
container_cursor_to_quoted
- [Code.Fragment] Add
:block_keyword_or_binary_operator
toCode.Fragment
for more precise suggestions after operators and closing terminators - [Code.Fragment] Add
Code.Fragment.lines/1
- [Enum] Provide more information on
Enum.OutOfBoundsError
- [Inspect] Allow
optional: :all
when deriving Inspect - [Inspect.Algebra] Add optimistic/pessimistic groups as a simplified implementation of
next_break_fits
- [IO.ANSI] Add ANSI codes to turn off conceal and crossed_out
- [Kernel] Allow controlling which applications are used during inference
- [Kernel] Support
min/2
andmax/2
as guards - [Kernel.ParallelCompiler] Add
each_long_verification_threshold
which invokes a callback when type checking a module takes too long - [Kernel.ParallelCompiler] Include lines in
== Compilation error in file ... ==
slogans - [Macro] Print debugging results from
Macro.dbg/3
as they happen, instead of once at the end - [Module] Do not automatically load modules after their compilation, guaranteeing a more con...
v1.18.4
This release includes initial support for Erlang/OTP 28, for those who want to try it out. In such cases, you may use Elixir v1.18.4 precompiled for Erlang/OTP 27, as it is binary compatible with Erlang/OTP 28. Note, however, that Erlang/OTP 28 no longer allows regexes to be defined in the module body and interpolated into an attribute. If you do this:
@some_attribute ~r/foo/ def some_fun, do: @some_attribute
You must rewrite it to:
def some_fun, do: ~r/foo/
1. Enhancements
IEx
- [IEx.Helpers] Add
IEx.Helpers.process_info/1
which prints process information
Mix
- [mix compile] Support the
--no-listeners
option - [mix local] Retry HTTP requests with disabled middlebox comp mode depending on the failure reason
- [mix local.hex] Install Hex per OTP release
- [mix local.rebar] Install Hex per OTP release
- [mix run] Support the
--no-listeners
option
2. Bug fixes
Elixir
- [Kernel] Emit trace events for
@on_definition
callbacks - [Kernel] Emit trace events for
@on_load
callbacks - [Kernel] Emit trace events for
super
calls - [Kernel] Emit trace events for imported function calls
- [Kernel] Optimize map unions to avoid building long lists
- [Kernel] Do not crash when type checking nested bitstrings in patterns
- [Kernel] Do not crash when non-binary bitstring is given as struct default value
- [Kernel] Recompile regexes when escaped from module attributes for Erlang/OTP 28 compatibility
- [Kernel] Preserve backwards compatibility in
elixir_erl
Mix
- [mix deps.get] Ensure git checkout works when there are untracked files in the dependency
- [mix loadpaths] Do not run listeners when not checking the deps
v1.18.3
1. Enhancements
Elixir
- [JSON] Encode any JSON key to string
- [Kernel] Allow
<<_::3*8>>
in typespecs
Mix
- [mix loadpaths] Support
--no-listeners
option
2. Bug fixes
Elixir
- [CLI] Fix
--no-color
not setting:ansi_enabled
to false - [Protocol] Return correct implementation for an invalid struct pointing to
nil
- [Stream] Do not raise when
Stream.cycle/1
is explicitly halted
ExUnit
- [ExUnit.Diff] Fix regression when diffing nested improper lists
IEx
- [IEx.Autocomplete] Fix autocomplete crash when expanding struct with
__MODULE__
- [IEx.Helpers] Do not purge on
recompile
if IEx is not running
v1.18.2
1. Enhancements
Elixir
- [CLI] Add
--color
/--no-color
for enabling and disabling of ANSI colors - [Code.Fragment] Provide more AST context when invoking
container_cursor_to_quoted
with trailing fragments - [Regex] Ensure compatibility with Erlang/OTP 28+ new Regex engine
Mix
- [mix] Print compilation lock waiting message to stderr
- [mix] Add an environment variable to optionally disable compilation locking
2. Bug fixes
Elixir
- [CLI] Temporarily remove PowerShell scripts for
elixir
,elixirc
, andmix
on Windows, as they leave the shell broken after quitting Erlang
ExUnit
- [ExUnit] Fix crash when diffing bitstring specifiers
IEx
- [IEx.Autocomplete] Fix crashing whhen autocompleting structs with runtime values
Mix
- [mix] Track compilation locks per user to avoid permission errors
- [mix deps.update] Ensure Git dependencies can be upgraded by doing so against the origin
v1.18.1
1. Enhancements
- [Kernel] Do not emit type violation warnings when comparing or matching against literals
- [Kernel] Do not validate clauses of private overridable functions
2. Bug fixes
Elixir
- [Code.Fragment] Ensure
Code.Fragment.container_cursor_to_quoted/2
with:trailing_fragment
parses expressions that were supported in previous versions - [Kernel] Do not crash when typing violation is detected on dynamic dispatch
- [Kernel] Properly annotate the source for warnings emitted by the compiler with the
@file
annotation - [Kernel] Properly annotate the source for warnings emitted by the type system with the
@file
annotation - [Kernel] Remove
:no_parens
metadata when using capture with arity on all cases - [Kernel] Ensure diagnostic traces are kept backwards compatible
ExUnit
- [ExUnit.Case] Ensure async groups do not run concurrenly while the test suite is still loading
- [ExUnit.Case] Ensure
--repeat-until-failure
can be combined with groups
Mix
- [mix compile.elixir] Store compilation results if compilation fails due to
--warnings-as-errors
- [mix deps.loadpaths] Add build lock
- [mix escript.build] Ensure build succeeds when protocol consolidation is disabled
- [Mix.Shell] Ensure encoding is properly respected on Windows and Unix systems