Improve error message for protocols with no implementation, closes #14364

This commit is contained in:
José Valim
2025-07-10 09:30:42 +02:00
parent 9619116cde
commit b878f37577
2 changed files with 60 additions and 6 deletions
+15 -5
View File
@@ -1031,11 +1031,21 @@ defmodule Module.Types.Apply do
Code.ensure_loaded?(mod) and
Keyword.has_key?(mod.module_info(:attributes), :__protocol__) ->
# Protocol errors can be very verbose, so we collapse structs
"""
but expected a type that implements the #{inspect(mod)} protocol, it must be one of:
#{clauses_args_to_quoted_string(clauses, converter, collapse_structs: true)}
"""
if function_exported?(mod, :__protocol__, 1) and
mod.__protocol__(:impls) == {:consolidated, []} do
"""
but the protocol was not yet implemented for any type and therefore will always fail. \
This error typically happens within libraries that define protocols and will disappear as \
soon as there is one implementation. If you expect the protocol to be implemented later on, \
you can define an implementation specific for development/test.
"""
else
# Protocol errors can be very verbose, so we collapse structs
"""
but expected a type that implements the #{inspect(mod)} protocol, it must be one of:
#{clauses_args_to_quoted_string(clauses, converter, collapse_structs: true)}
"""
end
true ->
"""
@@ -384,7 +384,7 @@ defmodule Module.Types.IntegrationTest do
assert_no_warnings(files)
end
test "mismatched impl" do
test "mismatched implementation" do
files = %{
"a.ex" => """
defprotocol Itself do
@@ -420,6 +420,50 @@ defmodule Module.Types.IntegrationTest do
assert_warnings(files, warnings)
end
@tag :require_ast
test "no implementation" do
files = %{
"a.ex" => """
defprotocol NoImplProtocol do
def callback(data)
end
""",
"b.ex" => """
defmodule NoImplProtocol.Caller do
def run do
NoImplProtocol.callback(:hello)
end
end
"""
}
warnings = [
"""
warning: incompatible types given to NoImplProtocol.callback/1:
NoImplProtocol.callback(:hello)
given types:
-:hello-
but the protocol was not yet implemented for any type and therefore will always fail. \
This error typically happens within libraries that define protocols and will disappear as \
soon as there is one implementation. If you expect the protocol to be implemented later on, \
you can define an implementation specific for development/test.
typing violation found at:
│
3 │ NoImplProtocol.callback(:hello)
│ ~
│
└─ b.ex:3:20: NoImplProtocol.Caller.run/0
"""
]
assert_warnings(files, warnings, consolidate_protocols: true)
end
@tag :require_ast
test "String.Chars protocol dispatch" do
files = %{