Skip to content

Commit 6710d7e

Browse files
gldubcjosevalim
authored andcommitted
Unify :empty_list and :list domains in maps
1 parent 7ad99b5 commit 6710d7e

File tree

2 files changed

+45
-19
lines changed

2 files changed

+45
-19
lines changed

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

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,8 @@ defmodule Module.Types.Descr do
2828

2929
defmacro bdd_leaf(arg1, arg2), do: {arg1, arg2}
3030

31-
@domain_key_types [
32-
:binary,
33-
:empty_list,
34-
:integer,
35-
:float,
36-
:pid,
37-
:port,
38-
:reference,
39-
:fun,
40-
:atom,
41-
:tuple,
42-
:map,
43-
:list
44-
]
31+
@domain_key_types [:binary, :integer, :float, :pid, :port, :reference] ++
32+
[:fun, :atom, :tuple, :map, :list]
4533

4634
# Remark: those are explicit BDD constructors. The functional constructors are `bdd_new/1` and `bdd_new/3`.
4735
@fun_top {:negation, %{}}
@@ -2274,17 +2262,28 @@ defmodule Module.Types.Descr do
22742262
for {type_kind, type} <- key_descr, reduce: [] do
22752263
acc ->
22762264
cond do
2277-
type_kind == :atom and match?({:union, _}, type) -> acc
2278-
type_kind == :bitmap -> bitmap_to_domain_keys(type, acc)
2279-
not empty?(%{type_kind => type}) -> [type_kind | acc]
2280-
true -> acc
2265+
type_kind == :list and
2266+
match?(%{bitmap: bitmap} when (bitmap &&& @bit_empty_list) != 0, key_descr) ->
2267+
acc
2268+
2269+
type_kind == :atom and match?({:union, _}, type) ->
2270+
acc
2271+
2272+
type_kind == :bitmap ->
2273+
bitmap_to_domain_keys(type, acc)
2274+
2275+
not empty?(%{type_kind => type}) ->
2276+
[type_kind | acc]
2277+
2278+
true ->
2279+
acc
22812280
end
22822281
end
22832282
end
22842283

22852284
defp bitmap_to_domain_keys(bitmap, acc) do
22862285
acc = if (bitmap &&& @bit_binary) != 0, do: [:binary | acc], else: acc
2287-
acc = if (bitmap &&& @bit_empty_list) != 0, do: [:empty_list | acc], else: acc
2286+
acc = if (bitmap &&& @bit_empty_list) != 0, do: [:list | acc], else: acc
22882287
acc = if (bitmap &&& @bit_integer) != 0, do: [:integer | acc], else: acc
22892288
acc = if (bitmap &&& @bit_float) != 0, do: [:float | acc], else: acc
22902289
acc = if (bitmap &&& @bit_pid) != 0, do: [:pid | acc], else: acc

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,33 @@ defmodule Module.Types.DescrTest do
17231723
{:ok, union(atom([:b]), pid() |> nil_or_type())}
17241724
end
17251725

1726+
test "map_get with lists" do
1727+
# Verify that empty_list() bitmap type maps to :list domain (not :empty_list domain)
1728+
map_with_list_domain = closed_map([{domain_key(:list), atom([:empty])}])
1729+
1730+
# empty_list() should access the :list domain
1731+
assert map_get(map_with_list_domain, empty_list()) == {:ok, atom([:empty]) |> nil_or_type()}
1732+
1733+
# non_empty_list() should also access the :list domain
1734+
assert map_get(map_with_list_domain, non_empty_list(integer())) ==
1735+
{:ok, atom([:empty]) |> nil_or_type()}
1736+
1737+
# list() should also access the :list domain
1738+
assert map_get(map_with_list_domain, list(integer())) ==
1739+
{:ok, atom([:empty]) |> nil_or_type()}
1740+
1741+
# If I create a map and instantiate both empty_list() and non_empty_list(integer()), it should return the union of the two types
1742+
map =
1743+
closed_map([{domain_key(:list), atom([:empty])}, {domain_key(:list), atom([:non_empty])}])
1744+
1745+
assert map_get(map, empty_list()) == {:ok, atom([:empty, :non_empty]) |> nil_or_type()}
1746+
1747+
assert map_get(map, non_empty_list(integer())) ==
1748+
{:ok, atom([:empty, :non_empty]) |> nil_or_type()}
1749+
1750+
assert map_get(map, list(integer())) == {:ok, atom([:empty, :non_empty]) |> nil_or_type()}
1751+
end
1752+
17261753
test "map_update" do
17271754
assert map_update(open_map(key: atom([:value])), atom([:key]), atom([:new_value])) ==
17281755
{:ok, open_map(key: atom([:new_value]))}

0 commit comments

Comments
 (0)