diff --git a/lib/elixir/test/elixir/behaviour_test.exs b/lib/elixir/test/elixir/behaviour_test.exs index 9ad68abb98f..f4093439163 100644 --- a/lib/elixir/test/elixir/behaviour_test.exs +++ b/lib/elixir/test/elixir/behaviour_test.exs @@ -3,30 +3,33 @@ Code.require_file "test_helper.exs", __DIR__ defmodule BehaviourTest do use ExUnit.Case, async: true - defmodule Sample do - use Behaviour + {_, _, sample_binary, _} = + defmodule Sample do + use Behaviour - defcallback first(integer) :: integer + defcallback first(integer) :: integer - defcallback foo(atom(), binary) :: binary + defcallback foo(atom(), binary) :: binary - defcallback bar(External.hello, my_var :: binary) :: binary + defcallback bar(External.hello, my_var :: binary) :: binary - defcallback guarded(my_var) :: my_var when my_var: binary + defcallback guarded(my_var) :: my_var when my_var: binary - defcallback orr(atom | integer) :: atom + defcallback orr(atom | integer) :: atom - defcallback literal(123, {atom}, :atom, [integer], true) :: atom + defcallback literal(123, {atom}, :atom, [integer], true) :: atom - defmacrocallback last(integer) :: Macro.t - end + defmacrocallback last(integer) :: Macro.t + end + + @sample_binary sample_binary test "callbacks" do assert Sample.__behaviour__(:callbacks) == [first: 1, guarded: 1, "MACRO-last": 2, literal: 5, orr: 1, foo: 2, bar: 2] end test "specs" do - assert length(Keyword.get_values(Sample.module_info[:attributes], :callback)) == 7 + assert length(Kernel.Typespec.beam_callbacks(@sample_binary)) == 7 end test "default is not supported" do diff --git a/lib/elixir/test/elixir/kernel/dialyzer_test.exs b/lib/elixir/test/elixir/kernel/dialyzer_test.exs index ba98f6d913d..6bfd4788580 100644 --- a/lib/elixir/test/elixir/kernel/dialyzer_test.exs +++ b/lib/elixir/test/elixir/kernel/dialyzer_test.exs @@ -53,6 +53,7 @@ defmodule Kernel.DialyzerTest do {:ok, [outdir: dir, dialyzer: dialyzer]} end + @tag otp19: false test "no warnings on valid remote calls", context do copy_beam! context, Dialyzer.RemoteCall assert_dialyze_no_warnings! context @@ -63,6 +64,7 @@ defmodule Kernel.DialyzerTest do assert_dialyze_no_warnings! context end + @tag otp19: false test "no warnings on raise", context do copy_beam! context, Dialyzer.Raise assert_dialyze_no_warnings! context diff --git a/lib/elixir/test/elixir/kernel/raise_test.exs b/lib/elixir/test/elixir/kernel/raise_test.exs index 8915b1d9264..a2ed4054ba8 100644 --- a/lib/elixir/test/elixir/kernel/raise_test.exs +++ b/lib/elixir/test/elixir/kernel/raise_test.exs @@ -283,9 +283,10 @@ defmodule Kernel.RaiseTest do end test "badfun error" do - x = :example + # Avoid "invalid function call" warning in >= OTP 19 + x = fn -> :example end result = try do - x.(2) + x.().(2) rescue x in [BadFunctionError] -> Exception.message(x) end diff --git a/lib/elixir/test/elixir/protocol_test.exs b/lib/elixir/test/elixir/protocol_test.exs index 33b881999f2..e7d1752607d 100644 --- a/lib/elixir/test/elixir/protocol_test.exs +++ b/lib/elixir/test/elixir/protocol_test.exs @@ -5,18 +5,24 @@ defmodule ProtocolTest do doctest Protocol - defprotocol Sample do - @type t :: any - @doc "Ok" - @spec ok(t) :: boolean - def ok(term) - end + {_, _, sample_binary, _} = + defprotocol Sample do + @type t :: any + @doc "Ok" + @spec ok(t) :: boolean + def ok(term) + end - defprotocol WithAny do - @fallback_to_any true - @doc "Ok" - def ok(term) - end + @sample_binary sample_binary + + {_, _, with_any_binary, _} = + defprotocol WithAny do + @fallback_to_any true + @doc "Ok" + def ok(term) + end + + @with_any_binary with_any_binary defprotocol Derivable do def ok(a) @@ -123,11 +129,11 @@ defmodule ProtocolTest do end test "protocol defines callbacks" do - assert get_callbacks(Sample, :ok, 1) == - [{:type, [11], :fun, [{:type, [11], :product, [{:user_type, [11], :t, []}]}, {:type, [11], :boolean, []}]}] + assert get_callbacks(@sample_binary, :ok, 1) == + [{:type, 12, :fun, [{:type, 12, :product, [{:user_type, 12, :t, []}]}, {:type, 12, :boolean, []}]}] - assert get_callbacks(WithAny, :ok, 1) == - [{:type, [18], :fun, [{:type, [18], :product, [{:user_type, [18], :t, []}]}, {:type, [18], :term, []}]}] + assert get_callbacks(@with_any_binary, :ok, 1) == + [{:type, 22, :fun, [{:type, 22, :product, [{:user_type, 22, :t, []}]}, {:type, 22, :term, []}]}] end test "protocol defines functions and attributes" do @@ -182,8 +188,8 @@ defmodule ProtocolTest do assert Multi.test(:a) == :a end - defp get_callbacks(module, name, arity) do - callbacks = for {:callback, info} <- module.__info__(:attributes), do: hd(info) + defp get_callbacks(beam, name, arity) do + callbacks = Kernel.Typespec.beam_callbacks(beam) List.keyfind(callbacks, {name, arity}, 0) |> elem(1) end @@ -308,6 +314,8 @@ defmodule Protocol.ConsolidationTest do {:ok, binary} = Protocol.consolidate(Sample, [Any, ImplStruct]) :code.load_binary(Sample, 'protocol_test.exs', binary) + @sample_binary binary + # Any should be moved to the end :code.purge(WithAny) :code.delete(WithAny) @@ -367,7 +375,7 @@ defmodule Protocol.ConsolidationTest do end test "consolidated keeps callbacks" do - callbacks = for {:callback, info} <- Sample.__info__(:attributes), do: hd(info) + callbacks = Kernel.Typespec.beam_callbacks(@sample_binary) assert callbacks != [] end diff --git a/lib/elixir/test/elixir/test_helper.exs b/lib/elixir/test/elixir/test_helper.exs index d919fb4ec04..c84f4f9bfc6 100644 --- a/lib/elixir/test/elixir/test_helper.exs +++ b/lib/elixir/test/elixir/test_helper.exs @@ -1,4 +1,10 @@ -ExUnit.start [trace: "--trace" in System.argv] +exclude = + case :erlang.system_info(:otp_release) do + '19' -> [otp19: false] + _ -> [] + end + +ExUnit.start [exclude: exclude, trace: "--trace" in System.argv] # Beam files compiled on demand path = Path.expand("../../tmp/beams", __DIR__) diff --git a/lib/iex/lib/iex/introspection.ex b/lib/iex/lib/iex/introspection.ex index 09be4694b4a..a73f7cdd80f 100644 --- a/lib/iex/lib/iex/introspection.ex +++ b/lib/iex/lib/iex/introspection.ex @@ -108,7 +108,7 @@ defmodule IEx.Introspection do if docs = Code.get_docs(mod, :docs) do if doc = find_doc(docs, fun, arity) do if callback_module = is_nil(elem(doc, 4)) and callback_module(mod, fun, arity) do - filter = &match?({^fun, _}, elem(&1, 0)) + filter = &match?({^fun, ^arity}, elem(&1, 0)) print_callback_docs(callback_module, filter, &print_doc/2) else print_doc(doc) @@ -147,14 +147,11 @@ defmodule IEx.Introspection do do: true defp callback_module(mod, fun, arity) do + filter = &match?({{^fun, ^arity}, _}, &1) mod.module_info(:attributes) |> Keyword.get_values(:behaviour) |> Stream.concat() - |> Enum.find(fn module -> - module.module_info(:attributes) - |> Enum.filter(&match?({:callback, _}, &1)) - |> Enum.any?(&match?({_, [{{^fun, ^arity}, _} | _]}, &1)) - end) + |> Enum.find(&Enum.any?(Typespec.beam_callbacks(&1), filter)) end defp print_doc({{fun, _}, _line, kind, args, doc}) do diff --git a/lib/iex/test/iex/helpers_test.exs b/lib/iex/test/iex/helpers_test.exs index b96b57cf0c7..6d88851f6bc 100644 --- a/lib/iex/test/iex/helpers_test.exs +++ b/lib/iex/test/iex/helpers_test.exs @@ -77,14 +77,17 @@ defmodule IEx.HelpersTest do @doc "Docs for MyBehaviour.first" @callback first(integer) :: integer @callback second(integer) :: integer + @callback second(integer, integer) :: integer end """ impl = """ defmodule Impl do @behaviour MyBehaviour def first(0), do: 0 - @doc "Docs for Impl.second" + @doc "Docs for Impl.second/1" def second(0), do: 0 + @doc "Docs for Impl.second/2" + def second(0, 0), do: 0 end """ files = ["my_behaviour.ex", "impl.ex"] @@ -92,10 +95,11 @@ defmodule IEx.HelpersTest do assert c(files, ".") |> Enum.sort == [Impl, MyBehaviour] assert capture_io(fn -> h Impl.first/1 end) == "* @callback first(integer()) :: integer()\n\nDocs for MyBehaviour.first\n" - assert capture_io(fn -> h Impl.second/1 end) == "* def second(int)\n\nDocs for Impl.second\n" + assert capture_io(fn -> h Impl.second/1 end) == "* def second(int)\n\nDocs for Impl.second/1\n" + assert capture_io(fn -> h Impl.second/2 end) == "* def second(int1, int2)\n\nDocs for Impl.second/2\n" assert capture_io(fn -> h Impl.first end) == "* @callback first(integer()) :: integer()\n\nDocs for MyBehaviour.first\n" - assert capture_io(fn -> h Impl.second end) == "* def second(int)\n\nDocs for Impl.second\n" + assert capture_io(fn -> h Impl.second end) == "* def second(int)\n\nDocs for Impl.second/1\n* def second(int1, int2)\n\nDocs for Impl.second/2\n" end after cleanup_modules([Impl, MyBehaviour]) diff --git a/lib/iex/test/test_helper.exs b/lib/iex/test/test_helper.exs index c3d57182311..fc18f466282 100644 --- a/lib/iex/test/test_helper.exs +++ b/lib/iex/test/test_helper.exs @@ -70,4 +70,3 @@ defmodule IEx.Case do |> String.trim end end -