Elixir v1.15.0-rc.0 released

This release requires Erlang/OTP 24 and later.

Elixir v1.15 is a smaller release with focused improvements
on compilation and boot times. This release also completes
our integration process with Erlang/OTP logger, bringing new
features such as log rotation and compaction out of the box.

You will also find additional convenience functions in Code,
Map, Keyword, all Calendar modules, and others.

Compile and boot-time improvements

The last several releases brought improvements to compilation
time and this version is no different. In particular, Elixir
now caches and prunes load paths before compilation, ensuring your
project (and dependencies!) compile faster and in an environment
closer to production.

In a nutshell the Erlang VM loads modules from code paths. Each
application that ships with Erlang and Elixir plus each dependency
become an entry in your code path. The larger the code path, the
more work Erlang has to do in order to find a module.

In previous versions, Mix would only add entries to the load paths.
Therefore, if you compiled 20 dependencies and you went to compile
the 21st, the code path would have 21 entries (plus all Erlang and
Elixir apps). This allowed modules from unrelated dependencies to
be seen and made compilation slower the more dependencies you had.
With this release, we will now prune the code paths to only the ones
listed as dependencies, bringing the behaviour closer to mix release.

Furthermore, Erlang/OTP 26 allows us to start applications
concurrently and cache the code path lookups, decreasing the cost of
booting applications. The combination of Elixir v1.15 and Erlang/OTP 26
should reduce the boot time of applications, such as when starting
iex -S mix or running a single test with mix test, from 5% to 30%.

The compiler is also smarter in several ways: @behaviour declarations
no longer add compile-time dependencies and aliases in patterns and
guards add no dependency whatsoever, as no dispatching happens. Furthermore,
Mix now tracks the digests of @external_resource files, reducing the
amount of recompilation when swapping branches. Finally, dependencies
are automatically recompiled when their compile-time configuration changes.

Potential incompatibilities

Due to the code path pruning, if you have an application or dependency
that does not specify its dependencies on Erlang and Elixir application,
it may no longer compile successfully in Elixir v1.15. You can temporarily
disable code path pruning by setting prune_code_paths: false in your
mix.exs, although doing so may lead to runtime bugs that are only
manifested inside a mix release.

Compiler warnings and errors

The Elixir compiler can now emit many errors for a single file, making
sure more feedback is reported to developers before compilation is aborted.

In Elixir v1.14, an undefined function would be reported as:

** (CompileError) undefined function foo/0 (there is no such import)
    my_file.exs:1

In Elixir v1.15, the new reports will look like:

error: undefined function foo/0 (there is no such import)
  my_file.exs:1

** (CompileError) nofile: cannot compile file (errors have been logged)

A new function, called Code.with_diagnostics/2, has been added so this
information can be leveraged by editors, allowing them to point to several
errors at once.

Integration with Erlang/OTP logger

This release provides additional features such as global logger
metadata and file logging (with rotation and compaction) out-of-the-box!

This release also soft-deprecates Elixir’s Logger Backends in
favor of Erlang’s Logger handlers. Elixir will automatically
convert your :console backend configuration into the new
configuration. Previously, you would set:

config :logger, :console,
  level: :error,
  format: "$time $message $metadata"

Which is now translated to the equivalent:

config :logger, :default_handler,
  level: :error

config :logger, :default_formatter,
  format: "$time $message $metadata"

If you use Logger.Backends.Console or other backends, they are
still fully supported and functional. If you implement your own
backends, you want to consider migrating to
:logger_backends
in the long term.

See the new Logger documentation for more information on the
new features and on compatibility.

v1.15.0-rc.0 (2022-05-22)

1. Enhancements

EEx

  • [EEx] Include source code snippets in syntax errors

Elixir

  • [Calendar] Add support for epoch time (%s) to Calendar.strftime/2
  • [Code] Code.format_string!/2 now converts 'charlists' into ~c"charlists" by default
  • [Code] Add :on_undefined_variable to the compiler options to preserve the warning behaviour which was deprecated back in Elixir v1.4
  • [Code] Add Code.loaded?/1 and Code.ensure_all_loaded(!)/1
  • [Code] Add Code.prepend_paths/1, Code.append_paths/1, and Code.delete_paths/1
  • [Code] Add Code.with_diagnostics/2 to return diagnostics when compiling and evaluating code
  • [Code.Fragment] Support nested expressions in Code.Fragment.cursor_context/1
  • [Code.Fragment] Keep operators and no paren calls in Code.Fragment.container_cursor_to_quoted/1
  • [Date] Add Date.before?/2 and Date.after?/2
  • [DateTime] Add DateTime.before?/2 and DateTime.after?/2
  • [DateTime] Support precision in DateTime.utc_now/2
  • [Inspect] Inspect now renders 'charlists' as ~c"charlists" by default
  • [Kernel] Break down case and cond inside dbg/2
  • [Kernel] Add t:nonempty_binary/0 and t:nonempty_bitstring/0
  • [Kernel] Treat @behaviours as runtime dependencies
  • [Kernel] Do not add runtime dependencies for alias references in patterns and guards
  • [Kernel] Warn for nested calls without parens inside keywords
  • [Kernel] Support for multi-letter uppercase sigils
  • [Kernel] Introduce mechanism to collect several errors in a module. Previously, as soon as there was a compilation error, compilation would fail. Now the compiler became a bit smarter and will report multiple errors whenever possible as multiple error: ... messages, similar to warning: ...
  • [Kernel.CLI] Support --sname undefined/--name undefined so a name is automatically generated
  • [Keyword] Add Keyword.split_with/2
  • [Macro] Improve error message when piping into an expression ending in bracket-based access
  • [Macro.Env] Add Macro.Env.lookup_alias_as/2
  • [Map] Add Map.split_with/2
  • [Map] Add Map.intersect/2 and Map.intersect/3
  • [MapSet] Add MapSet.split_with/2
  • [MapSet] Optimize most functions
  • [NaiveDateTime] Add NaiveDateTime.beginning_of_day/1 and NaiveDateTime.end_of_day/1
  • [NaiveDateTime] Add NaiveDateTime.before?/2 and NaiveDateTime.after?/2
  • [NaiveDateTime] Support precision in NaiveDateTime.utc_now/2
  • [OptionParser] Support :return_separator option
  • [Process] Add Process.alias/0,1 and Process.unalias/1
  • [Range] Add Range.split/2
  • [String] Update Unicode to version 15.0.0
  • [String] Add :fast_ascii mode to String.valid?/2
  • [Supervisor] Add support for automatic shutdown in Supervisor
  • [System] Support :lines in System.cmd/3 to capture output line by line
  • [Task] Remove head of line blocking on Task.yield_many/2
  • [Task] Enable selective receive optimizations in Erlang/OTP 26+
  • [Task.Supervisor] Do not copy args on temporary Task.Supervisor.start_child/2
  • [Time] Add Time.before?/2 and Time.after?/2
  • [URI] Add URI.append_path/2

ExUnit

  • [ExUnit] Add more color configuration to ExUnit CLI formatter
  • [ExUnit.Callbacks] Accept {module, function} tuples in ExUnit setup callbacks
  • [ExUnit.Doctest] Add ExUnit.DocTest.doctest_file/2
  • [ExUnit.Formatter] When comparing two anonymous functions, defined at the same place but capturing a different environment, we will now also diff the environments

IEx

  • [IEx] Make pry opt-in on dbg with --dbg pry
  • [IEX] Support IEX_HOME
  • [IEx.Autocomplete] Only provide aliases when autocompleting alias, import, and require
  • [IEx.Autocomplete] Provide field completion on map and struct updates
  • [IEx.Helpers] Add runtime_info(:allocators)
  • [IEx.Info] Implement protocol for Range, DateTime, and Regex

Logger

  • [Logger] Add Logger.add_handlers/1 and Logger.default_formatter/1
  • [Logger] Introduce default_formatter and default_handler configuration for Logger which configures Erlang/OTP logger
  • [Logger] Add :always_evaluate_messages configuration to Logger
  • [Logger.Formatter] Implement the Erlang Logger formatter API
  • [Logger.Formatter] Add support for ports in Logger metadata

Mix

  • [mix app.start] Allow applications to be started concurrently via the :start_concurrently configuration
  • [mix compile] Set --all-warnings by default
  • [mix compile] Reduce the amount of filesystem lookups for path dependencies by storing timestamps in manifests
  • [mix compile] Track digests of @external_resources
  • [mix compile.app] Write optional_applications to .app file
  • [mix compile.elixir] Add --purge-consolidation-path-if-stale which will purge the given consolidation path if compilation is required
  • [mix deps.compile] Automatically recompile dependencies if their compile env changes
  • [mix deps.get] Automatically install Hex and Rebar on mix deps.get/mix deps.update
  • [mix deps.get] Support --check-locked which raises if changes to the lockfile are required
  • [mix eval] Allow passing additional arguments
  • [mix format] Support --no-exit option
  • [mix format] Allow multiple formatters per file extension and sigil
  • [mix format] Show diffs whenever --check-formatted fails
  • [mix format] Allow the formatting root to be configured
  • [mix loadpaths] Cache deps and archive loadpaths in Erlang/OTP 26
  • [mix profile.fprof] Support --trace-to-file to improve performance when working with large outputs
  • [mix release] Allow passing additional arguments to the eval command
  • [mix xref graph] Support --output flag
  • [Mix.Project] Support def cli to unify all CLI defaults in a single place
  • [Mix.Project] Add Mix.Project.deps_tree/1

2. Bug fixes

Elixir

  • [Code.Formatter] Fix a scenario where a keyword followed by parenthesis could go above the maximum line length
  • [Code.Formatter] Remove unnecessary parens in nullary type funs
  • [Exception] Fix operator precedence when printing guards in Exception.blame/3
  • [File] Do not raise if there are file system race conditions in File.cp/2
  • [File] Do not raise when deleting write-only empty directories on File.rm_rf/1
  • [Kernel] Expand macros on the left side of → in try/rescue
  • [Kernel] Raise on misplaced ... inside typespecs
  • [Kernel] Do not import behaviour_info and module_info functions from Erlang modules
  • [Kernel.ParallelCompiler] Make sure compiler doesn’t crash when there are stray messages in the inbox
  • [Kernel.ParallelCompiler] Track compile and runtime warnings separately
  • [System] Fix race condition when a script would terminate before System.stop/1 executes
  • [URI] Make sure URI.merge/2 works accordingly with relative paths

ExUnit

  • [ExUnit] Fix crash when @tag capture_log: true was set to true and the Logger application was shut down in the middle of the test
  • [ExUnit] Do not merge context as tags inside the runner to reduce memory usage when emitting events to formatters
  • [ExUnit] Do not expand or collect vars from quote in ExUnit assertions

IEx

  • [IEx] Do not spawn a process to read IO. This fixes a bug where multiline paste stopped working
    whenever the input reader was killed
  • [IEx] Do not perform completion for prompts triggered during code evaluation

Mix

  • [mix compile] Include cwd in compiler cache key
  • [mix release] Fix Windows service when invoking erlsrv.exe in path with spaces

3. Soft deprecations (no warnings emitted)

Elixir

  • [File] File.cp/3 and File.cp_r/3 with a function as third argument
    is deprecated in favor of a keyword list
  • [Kernel.ParallelCompiler] Require the :return_diagnostics option to be
    set to true when compiling or requiring code

Logger

  • [Logger] add_backend/2, remove_backend/2, and configure_backend/2 have been deprecated
    in favor of the new :logger_backends dependency
  • [Logger] The :console configuration has been deprecated in favor of :default_formatter
  • [Logger] The :backends configuration has been deprecated in favor of Logger.add_handlers/1

Mix

  • [Mix.Project] :preferred_cli_env is deprecated in favor of :preferred_envs in def cli
  • [Mix.Project] :preferred_cli_target is deprecated in favor of :preferred_targets in def cli
  • [mix local] The environment variable HEX_MIRROR is deprecated in favor of HEX_BUILDS_URL

4. Hard deprecations

Elixir

  • [Calendar] Calendar.ISO.day_of_week/3 is deprecated in favor of Calendar.ISO.day_of_week/4
  • [Exception] Exception.exception?/1 is deprecated in favor of Kernel.is_exception/1
  • [Kernel] Deprecate ... as a valid function call identifier
  • [Regex] Regex.regex?/1 is deprecated in favor of Kernel.is_struct/2

Logger

  • [Logger] Logger.warn/2 is deprecated in favor of Logger.warning/2
57 Likes

Hi folks, I want to highlight one potential incompatibility with this release. Packages that previously would fail only when running a mix release due to poor configuration, will now fail to compile (better to know earlier than just in prod). If a package fails to compile when upgrading, try this:

  1. Update the package

  2. If that doesn’t fix it and the package is an Erlang package, force it to be compiled with manager: :rebar3. For example, ssl_verify_fun has such issue, therefore you could add to your mix.exs deps: {:ssl_verify_fun, ">= 0.0.0", manager: :rebar3}.

  3. If that doesn’t work, then set prune_code_paths: false to your def project in mix.exs

Please give the release a try and let us know! :heart:

15 Likes

I found a first problem even before installing new Elixir version. :sweat_smile:

Looks like buildds.hex.pm caches HTTP requests, so when asdf-elixir in list-all script calls curl -Lfs 'https://builds.hex.pm/builds/elixir/builds.txt' it gets all releases except the v1.15.0-rc.0* ones. I can reproduce it in console with above call.

Of course asdf users still can install it by calling asdf install elixir 1.15.0-rc.0-otp-26, but because of server cache we lost the autocompletion (again for this version only) …

I have found a workaround in the console. We can simply use same curl command, but with adding let’s say some parameter which server would not use anyway, for example ?a=5 url suffix would give back v1.15.0-rc.0* versions and proves that a cache problem happens on server side.

4 Likes

The feature used for the optimisation of Task looks weird interesting :slight_smile:

How exactly does it work? Is it documented somewhere?

4 Likes

We are investigating this one. We have been moving the builds from Bob to Elixir CI slowly and we battle test those changes on RCs (cause we don’t want to break the usual releases) and this time we found something. :slight_smile:

3 Likes

When do the docs appear on hexdocs?

Good question. Meanwhile you can access the Development documentation, see following links for more information:

https://hexdocs.pm/elixir/main

2 Likes

All of the build issues should have been addressed now. Let me know if that’s not the case.

2 Likes

Still curl command gives old result. :frowning:

Edit

For anyone interested I’m using for example:

curl -Lfs 'https://builds.hex.pm/builds/elixir/builds.txt' | cut -d\  -f1 | grep 15

Where:
  # curl
  -L, --location      Follow redirects
  -f, --fail          Fail silently (no output at all) on HTTP errors
  -s, --silent        Silent mode
  # i.e. curl does do anything with cache

  # cut
  -d, --delimiter=DELIM   use DELIM instead of TAB for field delimiter
  -f, --fields=LIST       select only these fields;  also print any line
                            that contains no delimiter character, unless
                            the -s option is specified
  # i.e. this line:
  # v0.15.0 2f2a52a64874a0a5b6d5c1fab812a80e94d982bc 2016-06-02T12:35:36Z
  # is trimmed to:
  # v0.15.0

and in this case it gives me:

v0.15.0
v0.15.1

As expected also asdf does not lists new Elixir version.

Edit

This may be helpful for others:

$ url="https://builds.hex.pm/builds/elixir/builds.txt"
$ curl  -Lfs "$url"  | cut -d\  -f1 | grep 15
v0.15.0
v0.15.1
$ curl -Lfs "$url?tmp=`uuidgen`"| cut -d\  -f1 | grep 15
v0.15.0
v0.15.1
v1.15.0-rc.0
v1.15.0-rc.0-otp-24
v1.15.0-rc.0-otp-25
v1.15.0-rc.0-otp-26

The second command ensures that every call would have unique value for tmp variable passed to server and therefore it’s avoiding cache problem.

@josevalim I can confirm that 1.15.0-rc.0* versions just appeared in asdf. :tada:

Edit: Yes, I have monitored it all the time. :sweat_smile:

1 Like

~OHBOY….if 26+26 wasn’t enough, what is?

yeah please never do this :slight_smile: as it will unnecessarily hit origin server, our storage bucket, every single time. Yes, (…)/builds.txt was stale but it would be fine and preferred if everyone went to something like (…)/builds.txt?0 instead, they’d all get the same fresh result. In any case the bug is fixed so this post is mostly moot. Thanks for looking into this and posting updates though!

3 Likes

I hope better naming of sigils for one :blush:: ~HTML

3 Likes

I’m seeing unexpected output from mix dialyzer but only with the combination:

  • Elixir 1.15.0-rc.0-otp-26
  • Erlang 26.0

I don’t see this output for any other combinations I’ve tried:

  • Elixir 1.15.0-rc.0-otp-25 with Erlang 25.3.2
  • Elixir 1.14.4-otp-26 with Erlang 26.0
  • Elixir 1.14.4-otp-25 with Erlang 25.3.2

The “errors” relate to transitive optional dependencies - they are not dependencies of ex_cldr_units. Interestingly there are other transitive optional dependencies that aren’t appearing in the messages!

I have tried adding the three libraries notes to :plt_add_apps to no avail (and fair enough, they aren’t actually configured in the lib being analysed - they are transitive optional dependencies).

Any help, clues, suggestions warmly welcomed.

==> ex_cldr_units
Compiling 24 files (.ex)
Generating MyApp.Cldr for 12 locales named [:af, :"af-NA", :ar, :bs, :de, ...] with a default locale named :en
warning: The locales [:af, :"af-NA", :ar, :bs, :de, :he, :ja, :se, :"se-SE"] configured in the CLDR backend MyApp.Cldr do not have localizations defined for additional units [:quarter].

Generating NoDocs.Cldr for 3 locales named [:en, :"en-001", :und] with a default locale named :"en-001"
Compiling mix/test_backend.ex (it's taking more than 10s)
Generated ex_cldr_units app
Finding suitable PLTs
Checking PLT...
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
Error loading gettext, dependency list may be incomplete.
 {~c"no such file or directory", ~c"gettext.app"}
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
Error loading gettext, dependency list may be incomplete.
 {~c"no such file or directory", ~c"gettext.app"}
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
Error loading gettext, dependency list may be incomplete.
 {~c"no such file or directory", ~c"gettext.app"}
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
Error loading gettext, dependency list may be incomplete.
 {~c"no such file or directory", ~c"gettext.app"}
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
[:asn1, :benchee, :castore, :certifi, :cldr_utils, :compiler, :crypto, :decimal, :deep_merge, :digital_token, :eex, :elixir, :ex_cldr, :ex_cldr_currencies, :ex_cldr_lists, :ex_cldr_numbers, :ex_unit, :gettext, :inets, :jason, :kernel, :logger, :mix, :nimble_parsec, :public_key, :ssl, :statistex, :stdlib]
PLT is up to date!
ignore_warnings: .dialyzer_ignore_warnings

Starting Dialyzer
[
  check_plt: false,
  init_plt: ~c"/Users/kip/Development/cldr_units/_build/dev/dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt",
  files: [~c"/Users/kip/Development/cldr_units/_build/dev/lib/ex_cldr_units/ebin/Elixir.Cldr.Unit.InvalidRangeError.beam",
   ~c"/Users/kip/Development/cldr_units/_build/dev/lib/ex_cldr_units/ebin/Elixir.NoDocs.Cldr.Locale.beam",
   ~c"/Users/kip/Development/cldr_units/_build/dev/lib/ex_cldr_units/ebin/Elixir.NoDocs.Cldr.AcceptLanguage.beam",
   ~c"/Users/kip/Development/cldr_units/_build/dev/lib/ex_cldr_units/ebin/Elixir.Inspect.Cldr.Unit.beam",
   ~c"/Users/kip/Development/cldr_units/_build/dev/lib/ex_cldr_units/ebin/Elixir.Cldr.Unit.Conversion.beam",
   ...],
  warnings: [:unknown]
]
Total errors: 0, Skipped: 0, Unnecessary Skips: 0
done in 0m8.49s
done (passed successfully)

Are those include as “concrete” dependencies somewhere? Does your application or any application that you depend on include them under applications in their .app file?

What about extending GenServer module with new non-blocking calls functionality added in OTP 23? Is it planned or did I miss something?

https://www.erlang.org/doc/man/gen_server.html#send_request-2

2 Likes

No, they aren’t. The only references grepped for certifi or castore are in cldr_utils and there are both optional: true.

A slightly simpler example is with the ex_cldr repo. Here’s the deps tree:

kip@Kips-MacBook-Pro cldr % mix deps.tree
ex_cldr
├── benchee ~> 1.0 (Hex package)
│   ├── deep_merge ~> 1.0 (Hex package)
│   └── statistex ~> 1.0 (Hex package)
├── cldr_utils ~> 2.21 (Hex package)
│   └── decimal ~> 1.9 or ~> 2.0 (Hex package)
├── decimal ~> 1.6 or ~> 2.0 (Hex package)
├── dialyxir ~> 1.0 (Hex package)
│   └── erlex >= 0.2.6 (Hex package)
├── ex_doc ~> 0.18 (Hex package)
│   ├── earmark_parser ~> 1.4.31 (Hex package)
│   ├── makeup_elixir ~> 0.14 (Hex package)
│   │   ├── makeup ~> 1.0 (Hex package)
│   │   │   └── nimble_parsec ~> 1.2.2 or ~> 1.3 (Hex package)
│   │   └── nimble_parsec ~> 1.2.3 or ~> 1.3 (Hex package)
│   └── makeup_erlang ~> 0.1 (Hex package)
│       └── makeup ~> 1.0 (Hex package)
├── gettext ~> 0.19 (Hex package)
│   └── expo ~> 0.4.0 (Hex package)
├── jason ~> 1.0 (Hex package)
│   └── decimal ~> 1.0 or ~> 2.0 (Hex package)
├── nimble_parsec ~> 0.5 or ~> 1.0 (Hex package)
├── stream_data ~> 0.4 (Hex package)
└── sweet_xml ~> 0.6 (Hex package)

There are no references to :certifi or :castore other than that they are optional dependencies in cldr_utils.

mix.lock

In mix.lock I see the following. There is not direct dependency on :certifi or :castore.

%{
  "benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"},
  "cldr_utils": {:hex, :cldr_utils, "2.24.0", "5b356769f2baf9dd25b166e9f1b2a5ce955d5b556bc07f56c959cfff1ec9543e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "3fde251e0bbbe473230561019dd6c2958d82a10c134bb5b8b4e21a694196cf85"},
  "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
 ...
}

Dialyzer run

And running rm -rf _build && mix dialyzer I see:

Generated ex_cldr app
Finding suitable PLTs
Checking PLT...
Error loading castore, dependency list may be incomplete.
 {~c"no such file or directory", ~c"castore.app"}
Error loading certifi, dependency list may be incomplete.
 {~c"no such file or directory", ~c"certifi.app"}
[:asn1, :castore, :certifi, :cldr_utils, :compiler, :crypto, :decimal, :earmark_parser, :eex, :elixir, :ex_doc, :ex_unit, :expo, :gettext, :inets, :jason, :kernel, :logger, :makeup, :makeup_elixir, :makeup_erlang, :mix, :nimble_parsec, :public_key, :ssl, :stdlib, :sweet_xml, :xmerl]
Looking up modules in dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt
Looking up modules in dialyxir_erlang-26.0_elixir-1.15.0-rc.0.plt
Finding applications for dialyxir_erlang-26.0_elixir-1.15.0-rc.0.plt
Finding modules for dialyxir_erlang-26.0_elixir-1.15.0-rc.0.plt
Checking 463 modules in dialyxir_erlang-26.0_elixir-1.15.0-rc.0.plt
Finding applications for dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt
Unknown application :castore
Unknown application :certifi
Finding modules for dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt
Copying dialyxir_erlang-26.0_elixir-1.15.0-rc.0.plt to dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt
Looking up modules in dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt
Checking 463 modules in dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt
Adding 626 modules to dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt
done in 0m24.86s
ignore_warnings: .dialyzer_ignore_warnings

Starting Dialyzer
[
  check_plt: false,
  init_plt: ~c"/Users/kip/Development/cldr/_build/dev/dialyxir_erlang-26.0_elixir-1.15.0-rc.0_deps-dev.plt",
  files: [~c"/Users/kip/Development/cldr/_build/dev/lib/ex_cldr/ebin/Elixir.Cldr.LanguageTag.Chars.Cldr.LanguageTag.U.beam",
   ~c"/Users/kip/Development/cldr/_build/dev/lib/ex_cldr/ebin/Elixir.Cldr.Normalize.CalendarEra.beam",
   ~c"/Users/kip/Development/cldr/_build/dev/lib/ex_cldr/ebin/Elixir.Cldr.NoParentError.beam",
   ~c"/Users/kip/Development/cldr/_build/dev/lib/ex_cldr/ebin/Elixir.Cldr.UnknownFormatError.beam",
   ~c"/Users/kip/Development/cldr/_build/dev/lib/ex_cldr/ebin/Elixir.Mix.Tasks.Cldr.Install.Locales.beam",
   ...],
  warnings: [:unknown]
]
Total errors: 0, Skipped: 0, Unnecessary Skips: 0
done in 0m14.19s
done (passed successfully)

ex_cldr.app

The relevant parts are:

{application,ex_cldr,
             [{compile_env,[{ecto,[json_library],error},
                            {ex_cldr,['Elixir.MyApp.Gettext'],
                                     {ok,[{default_locale,<<"en">>}]}},
                            {ex_cldr,[json_library],error},
                            {phoenix,[json_library],error}]},
              {optional_applications,[jason,nimble_parsec,gettext,sweet_xml]},
              {applications,[kernel,stdlib,elixir,logger,inets,ssl,eex,
                             ex_unit,cldr_utils,decimal,jason,ex_doc,
                             nimble_parsec,gettext,sweet_xml]},

There’s a lot more info on the PR that introduced the improved optimization to OTP 26:

2 Likes

Yeah, seen that and I think I get the concept, but I was wondering if it’s documented somewhere

There’s a brief discussion of this optimization in the Efficiency Guide that also mentions how to detect when it’s happening vs not (the recv_opt_info compiler flag).

3 Likes