Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions lib/elixir/lib/kernel/typespec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -938,17 +938,20 @@ defmodule Kernel.Typespec do

## Helpers

# This is a backport of Macro.expand/2 because we want to expand
# This is a modified backport of Macro.expand/2 because we want to expand
# aliases but we don't them to become compile-time references.
defp expand_remote({:__aliases__, meta, list} = alias, env) do
case :elixir_aliases.expand_or_concat(meta, list, env, true) do
receiver when is_atom(receiver) ->
receiver

[head | tail] ->
case Macro.expand_once(head, env) do
head when is_atom(head) -> :elixir_aliases.concat([head | tail])
_ -> alias
case Macro.expand(head, env) do
head when is_atom(head) ->
:elixir_aliases.concat([head | tail])

_ ->
compile_error(env, "unexpected expression in typespec: #{Macro.to_string(alias)}")
end
end
end
Expand Down
27 changes: 24 additions & 3 deletions lib/elixir/test/elixir/typespec_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ defmodule TypespecTest do
@type my_type :: %URI.t(){}
end
end

assert_raise Kernel.TypespecError,
~r"unexpected expression in typespec: t\.Foo",
fn ->
test_module do
@type my_type :: t.Foo
end
end
end

test "invalid function specification" do
Expand Down Expand Up @@ -120,7 +128,7 @@ defmodule TypespecTest do

test "redefined type" do
assert_raise Kernel.TypespecError,
~r"type foo/0 is already defined in .*test/elixir/typespec_test.exs:126",
~r"type foo/0 is already defined in .*test/elixir/typespec_test.exs:134",
fn ->
test_module do
@type foo :: atom
Expand All @@ -129,7 +137,7 @@ defmodule TypespecTest do
end

assert_raise Kernel.TypespecError,
~r"type foo/2 is already defined in .*test/elixir/typespec_test.exs:136",
~r"type foo/2 is already defined in .*test/elixir/typespec_test.exs:144",
fn ->
test_module do
@type foo :: atom
Expand All @@ -139,7 +147,7 @@ defmodule TypespecTest do
end

assert_raise Kernel.TypespecError,
~r"type foo/0 is already defined in .*test/elixir/typespec_test.exs:145",
~r"type foo/0 is already defined in .*test/elixir/typespec_test.exs:153",
fn ->
test_module do
@type foo :: atom
Expand Down Expand Up @@ -841,6 +849,19 @@ defmodule TypespecTest do
assert [{:atom, _, Keyword}, {:atom, _, :t}, [{:var, _, :value}]] = kw_with_value_args
end

test "@type with macro in alias" do
bytecode =
test_module do
defmacro module() do
quote do: __MODULE__
end

@type my_type :: module().Foo
end

assert [type: {:my_type, {:atom, _, TypespecTest.TypespecSample.Foo}, []}] = types(bytecode)
end

test "@type with a reserved signature" do
assert_raise Kernel.TypespecError,
~r"type required\/1 is a reserved type and it cannot be defined",
Expand Down
Loading