For example, in Plug, you might see:
[profile] lib/plug/conn.ex compiled in 935ms
[profile] lib/plug/ssl.ex compiled in 147ms (plus 744ms waiting)
[profile] lib/plug/static.ex compiled in 238ms (plus 654ms waiting)
[profile] lib/plug/csrf_protection.ex compiled in 237ms (plus 790ms waiting)
[profile] lib/plug/debugger.ex compiled in 719ms (plus 947ms waiting)
[profile] Finished compilation cycle of 60 modules in 1802ms
[profile] Finished group pass check of 60 modules in 75ms
This commit also increases the precision of --long-compilation-threshold
which now tracks only the time spent compiling and not the time waiting.
For this reason, we have reduced the threshold time to 10 seconds.
Previously, imports and requires were always added as
compile-time dependencies. With this change, they are
"export" dependencies, which are dependencies that depend
on the API defined by a module, such as struct and its
public definitions.
This change should drastically remove the amount of
modules recompiled in Elixir, making imports more feasible
for large projects.
We also don't hardcode the RELEASE_MODE config variable
inside Config.Provider, instead we use the application
environment. To make this possible, we simplify the boot
signature for the provider so it only calls boot/0 instead
of a dynamic app-key pair.
The dependency doesn't seem needed in this case.
We go through extra hoops to maintain dynamic invocations where
`opts` is not a compile-time list and :to is not a literal.
An easy way to see this optimization is:
defmodule A do
defdelegate f(), to: B
end
defmodule B do
def f() do
:ok
end
end
$ touch lib/b.ex && mix compile --verbose
Compiling 1 file (.ex)
Compiled lib/b.ex
vs:
defmodule A do
opts = [to: B]
defdelegate f(), opts
end
defmodule B do
def f() do
:ok
end
end
$ touch lib/b.ex && mix compile --verbose
Compiling 2 files (.ex)
Compiled lib/b.ex
Compiled lib/a.ex
#10033 added a third argument sorter_or_empty_fallback with a default value. To not break compatibility with existing code it also added a function clause that checks third argument's type with a guard and calls Enum.min_max_by/4 with appropriate arguments.
This commit fixes the following dialyzer warnings:
- In user code, e.g. `Enum.min_max_by([1, 2, 3], fn x -> x end, fn -> raise(Enum.EmptyError) end)`:
The function call will not succeed.
Enum.min_max_by([1, 2, 3], (_ -> any()), (() -> none()))
will never return since it differs in arguments with
positions 3rd from the success typing arguments:
(any(), (_ -> any()), atom() | (_, _ -> boolean()))
- When running dialyzer on Elixir itself (erlang notation):
Invalid type specification for function 'Elixir.Enum':min_max_by/3. The success typing is
(_, fun((_) -> any()), atom() | fun((_, _) -> boolean())) -> any()