Skip to content

Commit 8188424

Browse files
committed
Warn when defimp is called for consolidated protocol
Conflicts: lib/elixir/lib/protocol.ex
1 parent c07a34f commit 8188424

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

lib/elixir/lib/protocol.ex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ defmodule Protocol do
540540
"the dict[key] syntax, please implement the Dict behaviour instead"
541541
else
542542
Protocol.assert_protocol!(protocol)
543+
Protocol.__ensure_defimpl__(protocol, for, __ENV__)
543544
end
544545

545546
defmodule name do
@@ -580,6 +581,7 @@ defmodule Protocol do
580581
defp derive(protocol, for, struct, opts, env) do
581582
extra = ", cannot derive #{inspect protocol} for #{inspect for}"
582583
assert_protocol!(protocol, extra)
584+
__ensure_defimpl__(protocol, for, env)
583585
assert_impl!(protocol, Any, extra)
584586

585587
# Clean up variables from eval context
@@ -608,6 +610,17 @@ defmodule Protocol do
608610
end)
609611
end
610612

613+
@doc false
614+
def __ensure_defimpl__(protocol, for, env) do
615+
if Protocol.consolidated?(protocol) do
616+
message =
617+
"the #{inspect protocol} protocol has already been consolidated" <>
618+
", an implementation for #{inspect for} has no effect"
619+
:elixir_errors.warn(env.line, env.file, message)
620+
end
621+
:ok
622+
end
623+
611624
@doc false
612625
def __spec__?(module, name, arity) do
613626
signature = {name, arity}

lib/elixir/test/elixir/protocol_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,17 @@ defmodule Protocol.ConsolidationTest do
319319
refute Protocol.consolidated?(Enumerable)
320320
end
321321

322+
test "consolidation prevents new implementations" do
323+
assert ExUnit.CaptureIO.capture_io(:stderr, fn ->
324+
defimpl WithAny, for: Integer do
325+
def ok(_any), do: :ok
326+
end
327+
end) =~ ~r"warning: the .+WithAny protocol has already been consolidated"
328+
after
329+
:code.purge(WithAny.Atom)
330+
:code.delete(WithAny.Atom)
331+
end
332+
322333
test "consolidated implementations without any" do
323334
assert is_nil Sample.impl_for(:foo)
324335
assert is_nil Sample.impl_for(fn(x) -> x end)

0 commit comments

Comments
 (0)