Skip to content

Commit 24714c6

Browse files
committed
Improve error message for invalid default arguments
1 parent f088fc9 commit 24714c6

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

lib/elixir/lib/module/types/apply.ex

+18-5
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ defmodule Module.Types.Apply do
785785
def format_diagnostic({:badlocal, expr, args_types, domain, clauses, context}) do
786786
traces = collect_traces(expr, context)
787787
converter = &Function.identity/1
788-
{fun, _, _} = expr
788+
{fun, meta, _} = expr
789789

790790
explanation =
791791
empty_arg_reason(args_types) ||
@@ -794,16 +794,29 @@ defmodule Module.Types.Apply do
794794
#{clauses_args_to_quoted_string(clauses, converter)}
795795
"""
796796

797-
%{
798-
details: %{typing_traces: traces},
799-
message:
800-
IO.iodata_to_binary([
797+
banner =
798+
case fun == :super && meta[:default] && meta[:super] do
799+
{_kind, fun} ->
800+
"""
801+
incompatible types given as default arguments to #{fun}/#{length(args_types)}:
802+
"""
803+
804+
_ ->
801805
"""
802806
incompatible types given to #{fun}/#{length(args_types)}:
803807
804808
#{expr_to_string(expr) |> indent(4)}
805809
806810
given types:
811+
"""
812+
end
813+
814+
%{
815+
details: %{typing_traces: traces},
816+
message:
817+
IO.iodata_to_binary([
818+
banner,
819+
"""
807820
808821
#{args_to_quoted_string(args_types, domain, converter) |> indent(4)}
809822

lib/elixir/src/elixir_def.erl

+1-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ unpack_defaults(Kind, Meta, Name, Args, S, E) ->
314314
unpack_expanded(Kind, Meta, Name, [{'\\\\', DefaultMeta, [Expr, _]} | T] = List, VersionOffset, Acc, Clauses) ->
315315
Base = match_defaults(Acc, length(Acc) + VersionOffset, []),
316316
{Args, Invoke} = extract_defaults(List, length(Base) + VersionOffset, [], []),
317-
Clause = {Meta, Base ++ Args, [], {super, [{super, {Kind, Name}} | DefaultMeta], Base ++ Invoke}},
317+
Clause = {Meta, Base ++ Args, [], {super, [{super, {Kind, Name}}, {default, true} | DefaultMeta], Base ++ Invoke}},
318318
unpack_expanded(Kind, Meta, Name, T, VersionOffset, [Expr | Acc], [Clause | Clauses]);
319319
unpack_expanded(Kind, Meta, Name, [H | T], VersionOffset, Acc, Clauses) ->
320320
unpack_expanded(Kind, Meta, Name, T, VersionOffset, [H | Acc], Clauses);

lib/elixir/test/elixir/module/types/integration_test.exs

+33
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,39 @@ defmodule Module.Types.IntegrationTest do
244244
assert_no_warnings(files)
245245
end
246246

247+
test "incompatible default argument" do
248+
files = %{
249+
"a.ex" => """
250+
defmodule A do
251+
def ok(x = :ok \\\\ nil) do
252+
x
253+
end
254+
end
255+
"""
256+
}
257+
258+
warnings = [
259+
~S"""
260+
warning: incompatible types given as default arguments to ok/1:
261+
262+
-nil-
263+
264+
but expected one of:
265+
266+
dynamic(:ok)
267+
268+
typing violation found at:
269+
270+
2 │ def ok(x = :ok \\ nil) do
271+
│ ~
272+
273+
└─ a.ex:2:18: A.ok/0
274+
"""
275+
]
276+
277+
assert_warnings(files, warnings)
278+
end
279+
247280
test "returns diagnostics with source and file" do
248281
files = %{
249282
"a.ex" => """

0 commit comments

Comments
 (0)