Skip to content

Commit 27d3574

Browse files
author
José Valim
committed
Improve docs about consolidation during tests, closes #7039
1 parent 34f0254 commit 27d3574

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

lib/elixir/lib/kernel.ex

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4396,14 +4396,44 @@ defmodule Kernel do
43964396
43974397
In order to speed up dispatching in production environments, where
43984398
all implementations are known up-front, Elixir provides a feature
4399-
called protocol consolidation. For this reason, all protocols are
4400-
compiled with `debug_info` set to `true`, regardless of the option
4401-
set by `elixirc` compiler. The debug info though may be removed after
4402-
consolidation.
4403-
4404-
Protocol consolidation is applied by default to all Mix projects.
4405-
For applying consolidation manually, please check the functions in
4406-
the `Protocol` module or the `mix compile.protocols` task.
4399+
called protocol consolidation. Consolidation directly links protocols
4400+
to their implementations in a way that invoking a function from a
4401+
consolidated protocol is equivalent to invoking two remote functions.
4402+
4403+
Protocol consolidation is applied by default to all Mix projects during
4404+
compilation. This may be an issue during test. For instance, if you want
4405+
to implement a protocol during test, the implementation will have no
4406+
effect, as the protocol has already been consolidated. One possible
4407+
solution is to include compilation directories that are specific to your
4408+
test environment in your mix.exs:
4409+
4410+
def project do
4411+
...
4412+
elixirc_paths: elixirc_paths(Mix.env)
4413+
...
4414+
end
4415+
4416+
defp elixirc_paths(:test), do: ["lib", "test/support"]
4417+
defp elixirc_paths(_), do: ["lib"]
4418+
4419+
And then you can define the implementations specific to the test environment
4420+
inside `test/support/some_file.ex`.
4421+
4422+
Another approach is to disable protocol consolidation during tests in your
4423+
mix.exs:
4424+
4425+
def project do
4426+
...
4427+
consolidate_protocols: Mix.env != :test
4428+
...
4429+
end
4430+
4431+
Although doing so is not recommended as it may affect your test suite
4432+
performance.
4433+
4434+
Finally note all protocols are compiled with `debug_info` set to `true`,
4435+
regardless of the option set by `elixirc` compiler. The debug info is
4436+
used for consolidation and it may be removed after consolidation.
44074437
"""
44084438
defmacro defprotocol(name, do_block)
44094439

lib/elixir/lib/protocol.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,10 @@ defmodule Protocol do
750750
def __ensure_defimpl__(protocol, for, env) do
751751
if Protocol.consolidated?(protocol) do
752752
message =
753-
"the #{inspect(protocol)} protocol has already been consolidated" <>
754-
", an implementation for #{inspect(for)} has no effect"
753+
"the #{inspect(protocol)} protocol has already been consolidated, an " <>
754+
"implementation for #{inspect(for)} has no effect. If you want to " <>
755+
"implement protocols after compilation or during tests, check the " <>
756+
"\"Consolidation\" section in the documentation for Kernel.defprotocol/2"
755757

756758
:elixir_errors.warn(env.line, env.file, message)
757759
end

0 commit comments

Comments
 (0)