Skip to content

Commit d713e47

Browse files
committed
Improve error message for invalid default arguments
1 parent 8e796fc commit d713e47

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ defmodule Module.Types.Apply do
796796
def format_diagnostic({:badlocal, expr, args_types, domain, clauses, context}) do
797797
traces = collect_traces(expr, context)
798798
converter = &Function.identity/1
799-
{fun, _, _} = expr
799+
{fun, meta, _} = expr
800800

801801
explanation =
802802
empty_arg_reason(args_types) ||
@@ -805,16 +805,29 @@ defmodule Module.Types.Apply do
805805
#{clauses_args_to_quoted_string(clauses, converter, [])}
806806
"""
807807

808-
%{
809-
details: %{typing_traces: traces},
810-
message:
811-
IO.iodata_to_binary([
808+
banner =
809+
case fun == :super && meta[:default] && meta[:super] do
810+
{_kind, fun} ->
811+
"""
812+
incompatible types given as default arguments to #{fun}/#{length(args_types)}:
813+
"""
814+
815+
_ ->
812816
"""
813817
incompatible types given to #{fun}/#{length(args_types)}:
814818
815819
#{expr_to_string(expr) |> indent(4)}
816820
817821
given types:
822+
"""
823+
end
824+
825+
%{
826+
details: %{typing_traces: traces},
827+
message:
828+
IO.iodata_to_binary([
829+
banner,
830+
"""
818831
819832
#{args_to_quoted_string(args_types, domain, converter) |> indent(4)}
820833

lib/elixir/src/elixir_def.erl

Lines changed: 1 addition & 1 deletion
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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,39 @@ defmodule Module.Types.IntegrationTest do
494494
assert_warnings(files, warnings, consolidate_protocols: true)
495495
end
496496

497+
test "incompatible default argument" do
498+
files = %{
499+
"a.ex" => """
500+
defmodule A do
501+
def ok(x = :ok \\\\ nil) do
502+
x
503+
end
504+
end
505+
"""
506+
}
507+
508+
warnings = [
509+
~S"""
510+
warning: incompatible types given as default arguments to ok/1:
511+
512+
-nil-
513+
514+
but expected one of:
515+
516+
dynamic(:ok)
517+
518+
typing violation found at:
519+
520+
2 │ def ok(x = :ok \\ nil) do
521+
│ ~
522+
523+
└─ a.ex:2:18: A.ok/0
524+
"""
525+
]
526+
527+
assert_warnings(files, warnings)
528+
end
529+
497530
test "returns diagnostics with source and file" do
498531
files = %{
499532
"a.ex" => """

0 commit comments

Comments
 (0)