Skip to content

Commit 41cf575

Browse files
authored
Hoist dynamic up on map creation (#13579)
1 parent 5f9e08b commit 41cf575

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

lib/elixir/lib/module/types/descr.ex

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ defmodule Module.Types.Descr do
5050
def atom(as), do: %{atom: atom_new(as)}
5151
def atom(), do: %{atom: @atom_top}
5252
def binary(), do: %{bitmap: @bit_binary}
53-
def closed_map(pairs), do: %{map: map_new(:closed, :maps.from_list(pairs))}
53+
def closed_map(pairs), do: map_descr(:closed, pairs)
5454
def empty_list(), do: %{bitmap: @bit_empty_list}
5555
def empty_map(), do: %{map: @map_empty}
5656
def integer(), do: %{bitmap: @bit_integer}
@@ -59,7 +59,7 @@ defmodule Module.Types.Descr do
5959
def list(), do: %{bitmap: @bit_list}
6060
def non_empty_list(), do: %{bitmap: @bit_non_empty_list}
6161
def open_map(), do: %{map: @map_top}
62-
def open_map(pairs), do: %{map: map_new(:open, :maps.from_list(pairs))}
62+
def open_map(pairs), do: map_descr(:open, pairs)
6363
def pid(), do: %{bitmap: @bit_pid}
6464
def port(), do: %{bitmap: @bit_port}
6565
def reference(), do: %{bitmap: @bit_reference}
@@ -597,15 +597,34 @@ defmodule Module.Types.Descr do
597597
# `%{..., a: if_set(not atom()), b: integer()}`. For maps with more keys,
598598
# each key in a negated literal may create a new union when eliminated.
599599

600+
defp map_descr(tag, fields) do
601+
case map_descr_pairs(fields, [], false) do
602+
{fields, true} ->
603+
%{dynamic: %{map: map_new(tag, fields |> Enum.reverse() |> :maps.from_list())}}
604+
605+
{_, false} ->
606+
%{map: map_new(tag, :maps.from_list(fields))}
607+
end
608+
end
609+
610+
defp map_descr_pairs([{key, value} | rest], acc, dynamic?) do
611+
case :maps.take(:dynamic, value) do
612+
:error -> map_descr_pairs(rest, [{key, value} | acc], dynamic?)
613+
{dynamic, _static} -> map_descr_pairs(rest, [{key, dynamic} | acc], true)
614+
end
615+
end
616+
617+
defp map_descr_pairs([], acc, dynamic?) do
618+
{acc, dynamic?}
619+
end
620+
600621
defp optional?(%{bitmap: bitmap}) when (bitmap &&& @bit_optional) != 0, do: true
601622
defp optional?(_), do: false
602623

603624
defp map_tag_to_type(:open), do: term_or_optional()
604625
defp map_tag_to_type(:closed), do: not_set()
605626

606-
# TODO: We need to propagate any dynamic up
607-
defp map_new(tag, fields), do: [{tag, fields, []}]
608-
defp map_descr(tag, fields), do: %{map: map_new(tag, fields)}
627+
defp map_new(tag, fields = %{}), do: [{tag, fields, []}]
609628

610629
@doc """
611630
Fetches the type of the value returned by accessing `key` on `map`
@@ -834,8 +853,8 @@ defmodule Module.Types.Descr do
834853

835854
defp map_pop_key(tag, fields, key) do
836855
case :maps.take(key, fields) do
837-
{value, fields} -> {value, map_descr(tag, fields)}
838-
:error -> {map_tag_to_type(tag), map_descr(tag, fields)}
856+
{value, fields} -> {value, %{map: map_new(tag, fields)}}
857+
:error -> {map_tag_to_type(tag), %{map: map_new(tag, fields)}}
839858
end
840859
end
841860

lib/elixir/test/elixir/module/types/descr_test.exs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,15 @@ defmodule Module.Types.DescrTest do
168168
end
169169
end
170170

171+
describe "creation" do
172+
test "map hoists dynamic" do
173+
assert dynamic(open_map(a: integer())) == open_map(a: dynamic(integer()))
174+
175+
assert dynamic(open_map(a: union(integer(), binary()))) ==
176+
open_map(a: dynamic(integer()) |> union(binary()))
177+
end
178+
end
179+
171180
describe "subtype" do
172181
test "bitmap" do
173182
assert subtype?(integer(), union(integer(), float()))
@@ -240,7 +249,7 @@ defmodule Module.Types.DescrTest do
240249

241250
describe "empty" do
242251
test "map" do
243-
assert intersection(closed_map(b: atom()), open_map(a: integer())) |> empty?
252+
assert intersection(closed_map(b: atom()), open_map(a: integer())) |> empty?()
244253
end
245254
end
246255

0 commit comments

Comments
 (0)