Skip to content

Commit

Permalink
User defined types with the name record fail to compile in 1.8.0-rc…
Browse files Browse the repository at this point in the history
….0 (#8569)

Closes #8564

This is my first attempt to contribute code to elixir, so please forgive me if this PR is completely naive.

Besides adding the `is_list/1` guards, I have updated the error message to specify that record specifications must use an atom `literal` as the name, to make it clear that the type `atom` is also not valid.


Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
  • Loading branch information
sneako authored and José Valim committed Jan 2, 2019
1 parent 9b54efb commit 5e715aa
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
10 changes: 6 additions & 4 deletions lib/elixir/lib/kernel/typespec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -578,11 +578,12 @@ defmodule Kernel.Typespec do
end

# Handle records
defp typespec({:record, meta, [atom]}, vars, caller, state) when is_atom(atom) do
defp typespec({:record, meta, [atom]}, vars, caller, state) do
typespec({:record, meta, [atom, []]}, vars, caller, state)
end

defp typespec({:record, meta, [tag, field_specs]}, vars, caller, state) when is_atom(tag) do
defp typespec({:record, meta, [tag, field_specs]}, vars, caller, state)
when is_atom(tag) and is_list(field_specs) do
# We cannot set a function name to avoid tracking
# as a compile time dependency because for records it actually is one.
case Macro.expand({tag, [], [{:{}, [], []}]}, caller) do
Expand All @@ -607,8 +608,9 @@ defmodule Kernel.Typespec do
end
end

defp typespec({:record, _meta, _args}, _vars, caller, _state) do
compile_error(caller, "invalid record specification, expected the record name to be an atom")
defp typespec({:record, _meta, [_tag, _field_specs]}, _vars, caller, _state) do
message = "invalid record specification, expected the record name to be an atom literal"
compile_error(caller, message)
end

# Handle ranges
Expand Down
17 changes: 14 additions & 3 deletions lib/elixir/test/elixir/typespec_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -571,14 +571,25 @@ defmodule TypespecTest do
end
end

test "@type with invalid record" do
assert_raise CompileError, ~r"invalid record specification", fn ->
test "@type with a record which declares the name as the type `atom` rather than an atom literal" do
assert_raise CompileError, ~r"expected the record name to be an atom literal", fn ->
test_module do
@type my_type :: record(atom)
@type my_type :: record(atom, field: :foo)
end
end
end

test "@type can be named record" do
bytecode =
test_module do
@type record :: binary
@spec foo?(record) :: boolean
def foo?(_), do: true
end

assert [type: {:record, {:type, _, :binary, []}, []}] = types(bytecode)
end

test "@type with an invalid map notation" do
assert_raise CompileError, ~r"invalid map specification", fn ->
test_module do
Expand Down

0 comments on commit 5e715aa

Please sign in to comment.