Improve error message for invalid default arguments

This commit is contained in:
José Valim
2025-01-02 18:36:27 +01:00
parent f088fc9cdb
commit 24714c68a7
3 changed files with 52 additions and 6 deletions
+18 -5
View File
@@ -785,7 +785,7 @@ defmodule Module.Types.Apply do
def format_diagnostic({:badlocal, expr, args_types, domain, clauses, context}) do
traces = collect_traces(expr, context)
converter = &Function.identity/1
{fun, _, _} = expr
{fun, meta, _} = expr
explanation =
empty_arg_reason(args_types) ||
@@ -794,16 +794,29 @@ defmodule Module.Types.Apply do
#{clauses_args_to_quoted_string(clauses, converter)}
"""
%{
details: %{typing_traces: traces},
message:
IO.iodata_to_binary([
banner =
case fun == :super && meta[:default] && meta[:super] do
{_kind, fun} ->
"""
incompatible types given as default arguments to #{fun}/#{length(args_types)}:
"""
_ ->
"""
incompatible types given to #{fun}/#{length(args_types)}:
#{expr_to_string(expr) |> indent(4)}
given types:
"""
end
%{
details: %{typing_traces: traces},
message:
IO.iodata_to_binary([
banner,
"""
#{args_to_quoted_string(args_types, domain, converter) |> indent(4)}
+1 -1
View File
@@ -314,7 +314,7 @@ unpack_defaults(Kind, Meta, Name, Args, S, E) ->
unpack_expanded(Kind, Meta, Name, [{'\\\\', DefaultMeta, [Expr, _]} | T] = List, VersionOffset, Acc, Clauses) ->
Base = match_defaults(Acc, length(Acc) + VersionOffset, []),
{Args, Invoke} = extract_defaults(List, length(Base) + VersionOffset, [], []),
Clause = {Meta, Base ++ Args, [], {super, [{super, {Kind, Name}} | DefaultMeta], Base ++ Invoke}},
Clause = {Meta, Base ++ Args, [], {super, [{super, {Kind, Name}}, {default, true} | DefaultMeta], Base ++ Invoke}},
unpack_expanded(Kind, Meta, Name, T, VersionOffset, [Expr | Acc], [Clause | Clauses]);
unpack_expanded(Kind, Meta, Name, [H | T], VersionOffset, Acc, Clauses) ->
unpack_expanded(Kind, Meta, Name, T, VersionOffset, [H | Acc], Clauses);
@@ -244,6 +244,39 @@ defmodule Module.Types.IntegrationTest do
assert_no_warnings(files)
end
test "incompatible default argument" do
files = %{
"a.ex" => """
defmodule A do
def ok(x = :ok \\\\ nil) do
x
end
end
"""
}
warnings = [
~S"""
warning: incompatible types given as default arguments to ok/1:
-nil-
but expected one of:
dynamic(:ok)
typing violation found at:
│
2 │ def ok(x = :ok \\ nil) do
│ ~
│
└─ a.ex:2:18: A.ok/0
"""
]
assert_warnings(files, warnings)
end
test "returns diagnostics with source and file" do
files = %{
"a.ex" => """