Releases: elixir-lang/elixir
v1.8.0
Elixir v1.8 comes with many improvements at the infrastructure level, improving compilation time, speeding up common patterns, and adding features around introspection of the system.
Custom struct inspections
Elixir now provides a derivable implementation of the Inspect
protocol. In a nutshell, this means it is really easy to filter data from your data structures whenever they are inspected. For example, imagine you have a user struct with security and privacy sensitive information:
defmodule User do
defstruct [:id, :name, :age, :email, :encrypted_password]
end
By default, if you inspect a user via inspect(user)
, it will include all fields. This can cause fields such as :email
and :encrypted_password
to appear in logs, error reports, etc. You could always define a custom implementation of the Inspect
protocol for such cases but Elixir v1.8 makes it simpler by allowing you to derive the Inspect
protocol:
defmodule User do
@derive {Inspect, only: [:id, :name, :age]}
defstruct [:id, :name, :age, :email, :encrypted_password]
end
Now all user structs will be printed with all remaining fields collapsed:
#User<id: 1, name: "Jane", age: 33, ...>
You can also pass @derive {Inspect, except: [...]}
in case you want to keep all fields by default and exclude only some.
Time zone database support
In Elixir v1.3, Elixir added four types, known as Calendar types, to work with dates and times: Time
, Date
, NaiveDateTime
(without time zone) and DateTime
(with time zone). Over the last releases we have added many enhancements to the Calendar types but the DateTime
module always evolved at a slower pace since Elixir did not provide support for a time zone database.
Elixir v1.8 now defines a Calendar.TimeZoneDatabase
behaviour, allowing developers to bring in their own time zone databases. By defining an explicit contract for time zone behaviours, Elixir can now extend the DateTime
API, adding functions such as DateTime.shift_zone/3
. By default, Elixir ships with a time zone database called Calendar.UTCOnlyTimeZoneDatabase
that only handles UTC.
Other Calendar related improvements include the addition of Date.day_of_year/1
, Date.quarter_of_year/1
, Date.year_of_era/1
, and Date.day_of_era/1
.
Faster compilation and other performance improvements
Due to improvements to the compiler made over the last year, Elixir v1.8 should compile code about 5% faster on average. This is yet another release where we have been able to reduce compilation times and provide a more joyful development experience to everyone.
The compiler also emits more efficient code for range checks in guards (such as x in y..z
), for charlists with interpolation (such as 'foo #{bar} baz'
), and when working with records via the Record
module.
Finally, EEx templates got their own share of optimizations, emitting more compact code that runs faster.
Improved instrumentation and ownership with $callers
The Task
module is one of the most common ways to spawn light-weight processes to perform work concurrently. Whenever you spawn a new process, Elixir annotates the parent of that process through the $ancestors
key. This information can be used by instrumentation tools to track the relationship between events occurring within multiple processes. However, many times, tracking only the $ancestors
is not enough.
For example, we recommend developers to always start tasks under a supervisor. This provides more visibility and allows us to control how those tasks are terminated when a node shuts down. In your code, this can be done by invoking something like: Task.Supervisor.start_child(MySupervisor, task_specification)
. This means that, although your code is the one who invokes the task, the actual parent of the task would be the supervisor, as the supervisor is the one spawning it. We would list the supervisor as one of the $ancestors
for the task, but the relationship between your code and the task is lost.
In Elixir v1.8, we now track the relationship between your code and the task via the $callers
key in the process dictionary, which aligns well with the existing $ancestors
key. Therefore, assuming the Task.Supervisor
call above, we have:
[your code] -- calls --> [supervisor] ---- spawns --> [task]
which means we store the following relationships:
[your code] [supervisor] <-- ancestor -- [task]
^ |
|--------------------- caller ---------------------|
When a task is spawned directly from your code, without a supervisor, then the process running your code will be listed under both $ancestors
and $callers
.
This small feature is very powerful. It allows instrumentation and monitoring tools to better track and relate the events happening in your system. This feature can also be used by tools like the "Ecto Sandbox". The "Ecto Sandbox" allows developers to run tests concurrently against the database, by using transactions and an ownership mechanism where each process explicitly gets a connection assigned to it. Without $callers
, every time you spawned a task that queries the database, the task would not know its caller, and therefore it would be unable to know which connection was assigned to it. This often meant features that relies on tasks could not be tested concurrently. With $callers
, figuring out this relationship is trivial and you have more tests using the full power of your machine.
1. Enhancements
EEx
- [EEx] Optimize the default template engine to compile and execute more efficiently
Elixir
- [Calendar] Add
Calendar.TimeZoneDatabase
and aCalendar.UTCOnlyTimeZoneDatabase
implementation - [Calendar] Add callbacks
day_of_year/3
,quarter_of_year/3
,year_of_era/1
, andday_of_era/3
- [Code.Formatter] Preserve user's choice of new line after most operators
- [Date] Add
Date.day_of_year/1
,Date.quarter_of_year/1
,Date.year_of_era/1
, andDate.day_of_era/1
- [DateTime] Add
DateTime.from_naive/3
,DateTime.now/1
, andDateTime.shift_zone/3
- [File] Allow
:raw
option inFile.exists?/2
,File.regular?/2
, andFile.dir?/2
- [File] Allow POSIX time as an integer in
File.touch/2
andFile.touch!/2
- [Inspect] Allow
Inspect
protocol to be derivable with the:only
/:except
options - [Kernel] Do not propagate counters to variables in quote inside another quote
- [Kernel] Warn on ambiguous use of
::
and|
in typespecs - [Kernel] Add
:delegate_to
@doc
metadata tag when usingdefdelegate
- [Kernel] Improve compile-time building of ranges via the
..
operator - [Kernel] Compile charlist interpolation more efficiently
- [Kernel] Add
floor/1
andceil/1
guards - [Kernel.SpecialForms] Add
:reduce
option tofor
comprehensions - [List] Add
List.myers_difference/3
andList.improper?/1
- [Macro] Add
Macro.struct!/2
for proper struct resolution during compile time - [Map] Optimize and merge nested maps
put
andmerge
operations - [Range] Add
Range.disjoint?/2
- [Record] Reduce memory allocation when updating multiple fields in a record
- [Registry] Allow associating a value on
:via
tuple - [String] Add
String.bag_distance/2
- [Task] Add
$callers
tracking toTask
- this makes it easier to find which process spawned a task and use it for tracking ownership and monitoring
ExUnit
- [ExUnit] Add
ExUnit.after_suite/1
callback - [ExUnit.Assertions] Show last N messages (instead of first N) from mailbox on
assert_receive
fail
IEx
- [IEx.Helpers] Add
port/1
andport/2
- [IEx.Server] Expose
IEx.Server.run/1
for custom IEx sessions with the ability to broker pry sessions
Mix
- [Mix] Add
Mix.target/0
andMix.target/1
to control dependency management per target - [Mix.Project] Add
:depth
and:parents
options todeps_paths/1
- [mix archive.install] Add a timeout when installing archives
- [mix compile] Include optional dependencies in
:extra_applications
- [mix escript.install] Add a timeout when installing escripts
- [mix format] Warn when the same file may be formatted by multiple
.formatter.exs
- [mix test] Allow setting the maximum number of failures via
--max-failures
- [mix test] Print a message instead of raising on unmatched tests inside umbrella projects
2. Bug fixes
Elixir
- [Calendar] Allow printing dates with more than 9999 years
- [Exception] Exclude deprecated functions in "did you mean?" hints
- [Float] Handle subnormal floats in
Float.ratio/1
- [Kernel] Remove
Guard test tuple_size(...) can never succeed
Dialyzer warning ontry
- [Kernel] Expand operands in
size*unit
bitstring modifier instead of expectingsize
andunit
to be literal integers - [Kernel] Do not deadlock on circular struct dependencies in typespecs
- [Kernel] Raise proper error message when passing flags to the Erlang compiler that Elixir cannot handle
- [Kernel] Do not leak variables in
cond
clauses with a single matching at compile-time clause - [NaiveDateTime] Do not accept leap seconds in builder and parsing functions
- [String] Fix ZWJ handling in Unicode grapheme clusters
- [StringIO] Handle non-printable args in StringIO gracefully
IEx
- [IEx.Helpers] Use typespec info (instead of docs chunk) and properly format callbacks in
b/1
Logger
- [Logger] Allow Logger backends to be dynamically removed when an application is shutting down
Mix
- [mix compile] Ensure changes in deps propagate to all umbrella children - this fix a long standing issue where updating a dependency would not recompile all projects accordingly, requiring a complete removal of
_build
- [mix compile] Av...
v1.8.0-rc.1
Release v1.8.0-rc.1
v1.8.0-rc.0
Release v1.8.0-rc.0
v1.7.4
1. Enhancements
Elixir
- [Kernel] Expand
left..right
at compile time in more cases, which leads to improved performance under different scenarios, especially onx in left..right
expressions
Mix
- [mix deps.loadpaths] Add
--no-load-deps
flag. This is useful for Rebar 3 compatibility
2. Bug fixes
Elixir
- [Calendar] Fix for converting from negative iso days on New Year in a leap year
- [Kernel] Ensure
@spec
,@callback
,@type
and friends can be read accordingly - [Module] Avoid warnings when using Module.eval_quoted in the middle of existing definitions
Mix
- [mix archive.build] Unload previous archive versions before building
- [mix format] Expand paths so mix format
path\for\windows.ex
works - [mix test] Ensure that
--cover
displays correct coverage in an umbrella app
Checksums
- Precompiled.zip SHA1: eb328d3b071b33d80ad4cb4b3b203c1b2d7a5186
- Precompiled.zip SHA512: 807002481ae129fa1610a1facabe19765e2542397923d5c89e16b58f54870f2e444973e136d6b1207190b3117c03a37430860b6e3e6b7d59b3afb1b01852c6e3
- Docs.zip SHA1: 47ae4cea91a2da8ff040e346c059afccbdbffa13
- Docs.zip SHA512: 5b760a37e45640ab5816ad3ef2b581071e534fd0c409aa1a5348ee9a44980b099f54d66a3f9228be4ece1481a24b7109b1c9ac01d0aa0df4713fb0be1ca2de35
v1.7.3
1. Bug fixes
ExUnit
- [ExUnit.Assertions] Do not attempt to expand
try/1
as it is a special form
Mix
- [mix compile.app] Do not include applications with
runtime: false
as a runtime dependency for applications coming from Hex
Checksums
- Precompiled.zip SHA1: 9bfe816aaedeb9c5d40095b4eb4f5cb07eb33c2b
- Precompiled.zip SHA512: f8b0ac405531d46f4b65f459970c4b82892f8db51028f172072748269a922db65cb58e36239cd26dc39e5bdebd08a0e630ecbc267b6ff55a15d188483d78a0e5
- Docs.zip SHA1: 3ef076afc86a10fb422ec340f57079bb2480863c
- Docs.zip SHA512: a3cf7bb9bf31ce4bdbaa44470c2be82f9482f3b8ff3eb7fec86ba89debcf639a27c0a045ea65ce8e80aa86c2e9e4bbb8fa98f6389a6093191518f2180833aa2d
v1.7.2
v1.7.2 (2018-08-05)
1. Bug fixes
Elixir
- [Kernel] Do not emit warnings for repeated docs over different clauses due to false positives
Mix
- [mix compile] Properly mark top-level dependencies as optional and as runtime. This fixes a bug where Mix attempted to start optional dependencies of a package when those optional dependencies were not available
- [mix compile] Avoid deadlock when a config has a timestamp later than current time
- [mix test] Do not fail suite if there are no test files
2. Enhancements
Elixir
- [DateTime] Take negative years into account in
DateTime.from_iso8601/1
Mix
- [mix help] Show task and alias help when both are available
Checksums
- Precompiled.zip SHA1: 97051389559547248d7e7f497ed3866ef11e3072
- Precompiled.zip SHA512: e7ebdfcd301737967d0c04df50d3ba5b5a0663d2a2e2ac771cf61b9aa8d73a8f64dd9a408890ff0e2db4e48df8f94ff4d5fb7060f25592411e54910cdfc567a0
- Docs.zip SHA1: 7fbcff81b1032570c1f9a0dfa232e8b1bdd0490a
- Docs.zip SHA512: 8625522139f6a961fedb18b00cc78cad5e344f17b5a8a72746ceb284aab3f712db4b7ad57a4cfb86cdfa799a6c0f0b0b6c417117865321bbb70b6bbe0d8f0dd6
v1.7.1
v1.7.1 (2018-07-26)
1. Bug fixes
Elixir
- [Calendar] Work-around a Dialyzer bug that causes it to loop for a long time, potentially indefinitely
Checksums
- Precompiled.zip SHA1: fb06a3d238b65705a0e36fe9c308eef3d8bb5d46
- Precompiled.zip SHA512: 75c1601d985988ecdfcd48892cde4058dd36e52a3aa1c2007290ce587d7fa131d066afc6c34ca9138cf66431de80369681c82cf6290c214853335471c1851deb
- Docs.zip SHA1: e1008908b0fb4e692893dcc5c745f1c219fced1e
- Docs.zip SHA512: d05d1df7d9dab315a96fd7c0a49214e743b6bbe66fbbc6a3d8933c37f9baa5995b061396254b55d8c6ce8d337ed1ae3fcc3f97e65dd1cd8be9d091ce3412e27a
v1.7.0
Elixir v1.7 is the last release to support Erlang/OTP 19. We recommend everyone to migrate to Erlang/OTP 20+.
Documentation metadata
Elixir v1.7 implements EEP 48. EEP 48 aims to bring documentation interoperability across all languages running on the Erlang VM. The documentation format proposed by EEP 48 also supports metadata, which is now fully exposed to Elixir developers:
@moduledoc "A brand new module"
@moduledoc authors: ["Jane", "Mary"], since: "1.4.0"
Passing metadata is supported on @doc
, @moduledoc
and @typedoc
.
To access the new documentation format, developers should use Code.fetch_docs/1
. The old documentation format is no longer available and the old Code.get_docs/2
function will return nil
accordingly.
Tools like IEx and ExDoc have been updated to leverage the new format and show relevant metadata to users. While Elixir allows any metadata to be given, those tools currently exhibit only :deprecated
and :since
. Other keys may be shown in the future.
The __STACKTRACE__
construct
Erlang/OTP 21.0 introduces a new way to retrieve the stacktrace that is lexically scoped and no longer relies on side-effects like System.stacktrace/0
does. Before one would write:
try do
... something that may fail ...
rescue
e ->
log(e, System.stacktrace())
reraise(e, System.stacktrace())
end
In Elixir v1.7, this can be written as:
try do
... something that may fail ...
rescue
e ->
log(e, __STACKTRACE__)
reraise(e, __STACKTRACE__)
end
This change may also yield performance improvements in the future, since the lexical scope allows us to track precisely when a stacktrace is used and we no longer need to keep references to stacktrace entries after the try
construct finishes.
Other parts of the exception system have been improved. For example, more information is provided in certain occurrences of ArgumentError
, ArithmeticError
and KeyError
messages.
Erlang/OTP logger integration
Erlang/OTP 21 includes a new :logger
module. Elixir v1.7 fully integrates with the new :logger
and leverages its metadata system. The Logger.Translator
mechanism has also been improved to export metadata, allowing custom Logger backends to leverage information such as:
-
:crash_reason
- a two-element tuple with the throw/error/exit reason as first argument and the stacktrace as second -
:initial_call
- the initial call that started the process -
:registered_name
- the process registered name as an atom
We recommend Elixir libraries that previously hooked into Erlang's :error_logger
to hook into Logger
instead, in order to support all current and future Erlang/OTP versions.
Other Logger improvements
Previously, Logger macros such as debug
, info
, and so on would always evaluate their arguments, even when nothing would be logged. From Elixir v1.7, the arguments are only evaluated when the message is logged.
The Logger configuration system also accepts a new option called :compile_time_purge_matching
that allows you to remove log calls with specific compile-time metadata. For example, to remove all logger calls from application :foo
with level lower than :info
, as well as remove all logger calls from Bar.foo/3
, you can use the following configuration:
config :logger,
compile_time_purge_matching: [
[application: :foo, level_lower_than: :info],
[module: Bar, function: "foo/3"]
]
ExUnit improvements
ExUnit has also seen its own share of improvements. Assertions such as assert some_fun(arg1, arg2, arg3)
will now include the value of each argument in the failure report:
1) test function call arguments (TestOneOfEach)
lib/ex_unit/examples/one_of_each.exs:157
Expected truthy, got false
code: assert some_vars(1 + 2, 3 + 4)
arguments:
# 1
3
# 2
7
stacktrace:
lib/ex_unit/examples/one_of_each.exs:158: (test)
Furthermore, failures in doctests are now colored and diffed.
On the mix test
side of things, there is a new --failed
flag that runs all tests that failed the last time they ran. Finally, coverage reports generated with mix test --cover
include a summary out of the box:
Generating cover results ...
Percentage | Module
-----------|--------------------------
100.00% | Plug.Exception.Any
100.00% | Plug.Adapters.Cowboy2.Stream
100.00% | Collectable.Plug.Conn
100.00% | Plug.Crypto.KeyGenerator
100.00% | Plug.Parsers
100.00% | Plug.Head
100.00% | Plug.Router.Utils
100.00% | Plug.RequestId
... | ...
-----------|--------------------------
77.19% | Total
1. Enhancements
Elixir
- [Calendar.ISO] Support negative dates in
Calendar.ISO
- [Calendar] Add
Calendar.months_in_year/1
callback - [Code] Add
Code.compile_file/2
that compiles files without leaving footprints on the system - [Code] Add
Code.purge_compiler_modules/0
that purges any compiler module left behind. This is useful for live systems dynamically compiling code - [Code] Add
Code.fetch_docs/1
that returns docs in the EEP 48 format - [Date] Add
Date.months_in_year/1
function - [DynamicSupervisor] Use the name of the
DynamicSupervisor
as the ID whenever possible - [Exception] Provide "did you mean" suggestions on KeyError
- [Exception] Provide more information on ArithmeticError on Erlang/OTP 21+
- [Function] Add
Function
module withcapture/3
,info/1
andinfo/2
functions - [GenServer] Support the new
handle_continue/2
callback on Erlang/OTP 21+ - [IO.ANSI] Add cursor movement to
IO.ANSI
- [Kernel] Support adding arbitrary documentation metadata by passing a keyword list to
@doc
,@moduledoc
and@typedoc
- [Kernel] Introduce
__STACKTRACE__
to retrieve the current stacktrace insidecatch
/rescue
(this will be a requirement for Erlang/OTP 21+) - [Kernel] Raise on unsafe variables in order to allow us to better track unused variables (also known as imperative assignment / variable leakage)
- [Kernel] Warn when using
length
to check if a list is not empty on guards - [Kernel] Add hints on mismatched
do
/end
and others pairs - [Kernel] Warn when comparing structs using the
>
,<
,>=
and<=
operators - [Kernel] Warn on unsupported nested comparisons such as
x < y < z
- [Kernel] Warn if redefining documentation across clauses of the same definition
- [Kernel] Warn on unnecessary quotes around atoms, keywords and calls
- [Macro] Add
Macro.special_form?/2
andMacro.operator?/2
that returnstrue
if the given name/arity is a special form or operator respectively - [Macro.Env] Add
Macro.Env.vars/1
andMacro.Env.has_var?/2
that gives access to environment data without accessing private fields - [Regex] Include endianness in the regex version. This allows regexes to be recompiled when an archive is installed in a system with a different endianness
- [Registry] Add
Registry.count/1
andRegistry.count_match/4
- [String] Update to Unicode 11
- [StringIO] Add
StringIO.open/3
- [System] Use ISO 8601 in
System.build_info/0
ExUnit
- [ExUnit.Assertion] Print the arguments in error reports when asserting on a function call. For example, if
assert is_list(arg)
fails, the argument will be shown in the report - [ExUnit.Diff] Improve diffing of lists when one list is a subset of the other
- [ExUnit.DocTest] Show colored diffs on failed doctests
- [ExUnit.Formatter] Excluded tests, via the
--exclude
and--only
flags, are now shown as "Excluded" in reports. Tests skipped via@tag :skip
are now exclusively shown as "Skipped" and in yellow
IEx
- [IEx.Helpers] Add
use_if_available/2
- [IEx.Helpers] Allow
force: true
option inrecompile/1
- [IEx.Helpers] Add
:allocators
pane toruntime_info/1
- [IEx.Helpers] Show documentation metadata in
h/1
helpers
Logger
- [Logger] Ensure nil metadata is always pruned
- [Logger] Only evaluate Logger macro arguments when the message will be logged
- [Logger] Add
:compile_time_purge_matching
to purge logger calls that match certain compile time metadata, such as module names and application names - [Logger] Log to
:stderr
if a backend fails and there are no other backends - [Logger] Allow translators to return custom metadata
- [Logger] Return
:crash_reason
,:initial_call
and:registered_name
as metadata in crash reports coming from Erlang/OTP
Mix
- [mix archive.install] Add support for the Hex organization via
--organization
- [mix archive.uninstall] Support
--force
flag - [mix compile] Improve support for external build tools such as
rebar
- [mix deps] Include
override: true
in rebar dependencies to make the behaviour closer to how rebar3 works (although diverged deps are still marked as diverged) - [mix escript.install] Add support for the Hex organization via
--organization
- [mix escript.uninstall] Support
--force
flag - [mix help] Also list aliases
- [mix local] Use ipv6 with auto fallback to ipv4 when downloading data
- [mix profile] Allow all profiling tasks to run programatically
- [mix test] Add
--failed
option that only runs previously failed tests - [mix test] Print coverage summary by default when the
--cover
flag is given - [Mix.Project] Add
Mix.Project.clear_deps_cache/0
- [Mix.Project] Add
Mix.Project.config_mtime/0
that caches the config mtime values to avoid filesystem access
2. Bug fixes
Elixir
- [IO.ANSI.Docs] Fix table column alignment when converting docs to ANSI escapes
- [Code] Ensure
string_to_quoted
...
v1.7.0-rc.1
Release v1.7.0-rc.1
v1.7.0-rc.0
Release v1.7.0-rc.0