diff --git a/lib/elixir/lib/task.ex b/lib/elixir/lib/task.ex index ef7af6ebd7a..ec881c4450a 100644 --- a/lib/elixir/lib/task.ex +++ b/lib/elixir/lib/task.ex @@ -1444,6 +1444,13 @@ defmodule Task do end end + # exported only to avoid dialyzer opaqueness check in internal Task modules + @doc false + @spec __alias__(pid()) :: Task.ref() + def __alias__(pid) do + build_alias(pid) + end + ## Optimizations defp build_monitor(pid) do diff --git a/lib/elixir/lib/task/supervisor.ex b/lib/elixir/lib/task/supervisor.ex index 59b63f680e0..a296e9bfe03 100644 --- a/lib/elixir/lib/task/supervisor.ex +++ b/lib/elixir/lib/task/supervisor.ex @@ -614,7 +614,7 @@ defmodule Task.Supervisor do case start_child_with_spec(supervisor, [get_owner(owner), :monitor], :temporary, shutdown) do {:ok, pid} -> if link_type == :link, do: Process.link(pid) - alias = :erlang.monitor(:process, pid, alias: :demonitor) + alias = Task.__alias__(pid) send(pid, {owner, alias, alias, get_callers(owner), {module, fun, args}}) %Task{pid: pid, ref: alias, owner: owner, mfa: {module, fun, length(args)}} diff --git a/lib/elixir/test/elixir/fixtures/dialyzer/opaque_inline.ex b/lib/elixir/test/elixir/fixtures/dialyzer/opaque_inline.ex deleted file mode 100644 index ce224ee523b..00000000000 --- a/lib/elixir/test/elixir/fixtures/dialyzer/opaque_inline.ex +++ /dev/null @@ -1,10 +0,0 @@ -defmodule Dialyzer.OpaqueInline do - @spec bar(MapSet.t()) :: term() - def bar(set) do - set - end - - def foo() do - bar(MapSet.new([1, 2, 3])) - end -end diff --git a/lib/elixir/test/elixir/fixtures/dialyzer/opaqueness.ex b/lib/elixir/test/elixir/fixtures/dialyzer/opaqueness.ex new file mode 100644 index 00000000000..12857f515fe --- /dev/null +++ b/lib/elixir/test/elixir/fixtures/dialyzer/opaqueness.ex @@ -0,0 +1,17 @@ +defmodule Dialyzer.Opaqueness do + @spec bar(MapSet.t()) :: term() + def bar(set) do + set + end + + def foo() do + # inlining of literals should not violate opaqueness check + bar(MapSet.new([1, 2, 3])) + end + + # Task.Supervisor returns a Task.t() containing an opaque Task.ref() + @spec run_task() :: Task.t() + def run_task do + Task.Supervisor.async(SupervisorName, fn -> :ok end) + end +end diff --git a/lib/elixir/test/elixir/kernel/dialyzer_test.exs b/lib/elixir/test/elixir/kernel/dialyzer_test.exs index 615f946b0d9..01aa977ecae 100644 --- a/lib/elixir/test/elixir/kernel/dialyzer_test.exs +++ b/lib/elixir/test/elixir/kernel/dialyzer_test.exs @@ -50,7 +50,9 @@ defmodule Kernel.DialyzerTest do Module, Protocol, String, - String.Chars + String.Chars, + Task, + Task.Supervisor ] files = Enum.map(mods, &:code.which/1) @@ -178,8 +180,8 @@ defmodule Kernel.DialyzerTest do assert_dialyze_no_warnings!(context) end - test "no warning on inlined calls returning opaque", context do - copy_beam!(context, Dialyzer.OpaqueInline) + test "no warning due to opaqueness edge cases", context do + copy_beam!(context, Dialyzer.Opaqueness) assert_dialyze_no_warnings!(context) end