Skip to content

Commit 2f19899

Browse files
committed
More tests around descr map_fetch
1 parent 36ce1f8 commit 2f19899

File tree

2 files changed

+41
-33
lines changed

2 files changed

+41
-33
lines changed

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

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -620,9 +620,13 @@ defmodule Module.Types.Descr do
620620
case :maps.take(:dynamic, descr) do
621621
:error ->
622622
if is_map_key(descr, :map) and map_only?(descr) do
623-
map_fetch_static(descr, key)
624-
|> none_if_not_set()
625-
|> badkey_if_empty_or_tag(false)
623+
{static_optional?, static_type} = map_fetch_static(descr, key) |> pop_optional()
624+
625+
if static_optional? or empty?(static_type) do
626+
:badkey
627+
else
628+
{false, static_type}
629+
end
626630
else
627631
:badmap
628632
end
@@ -631,11 +635,15 @@ defmodule Module.Types.Descr do
631635
{true, dynamic()}
632636

633637
{dynamic, static} ->
634-
if (is_map_key(dynamic, :map) or is_map_key(static, :map)) and map_only?(static) do
635-
{optional?, dynamic_type} = map_fetch_static(dynamic, key) |> pop_not_set()
638+
if is_map_key(dynamic, :map) and map_only?(static) do
639+
{dynamic_optional?, dynamic_type} = map_fetch_static(dynamic, key) |> pop_optional()
640+
{static_optional?, static_type} = map_fetch_static(static, key) |> pop_optional()
636641

637-
dynamic(dynamic_type)
638-
|> badkey_if_empty_or_tag(optional?)
642+
if static_optional? or empty?(dynamic_type) do
643+
:badkey
644+
else
645+
{dynamic_optional?, union(dynamic(dynamic_type), static_type)}
646+
end
639647
else
640648
:badmap
641649
end
@@ -651,11 +659,7 @@ defmodule Module.Types.Descr do
651659
end
652660
end
653661

654-
defp badkey_if_empty_or_tag(type, tag) do
655-
if empty?(type), do: :badkey, else: {tag, type}
656-
end
657-
658-
defp pop_not_set(type) do
662+
defp pop_optional(type) do
659663
case type do
660664
%{bitmap: @bit_optional} ->
661665
{true, Map.delete(type, :bitmap)}
@@ -668,13 +672,6 @@ defmodule Module.Types.Descr do
668672
end
669673
end
670674

671-
defp none_if_not_set(type) do
672-
case type do
673-
%{bitmap: bitmap} when (bitmap &&& @bit_optional) != 0 -> @none
674-
_ -> type
675-
end
676-
end
677-
678675
# Union is list concatenation
679676
defp map_union(dnf1, dnf2), do: dnf1 ++ dnf2
680677

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

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -259,30 +259,26 @@ defmodule Module.Types.DescrTest do
259259
end
260260

261261
test "map_fetch" do
262-
assert map_fetch(closed_map(a: integer()), :a) == {false, integer()}
263-
264262
assert map_fetch(term(), :a) == :badmap
265263
assert map_fetch(union(open_map(), integer()), :a) == :badmap
266-
assert map_fetch(dynamic(), :a) == {true, dynamic()}
267264

268-
assert intersection(dynamic(), open_map(a: integer()))
269-
|> map_fetch(:a) == {false, intersection(integer(), dynamic())}
265+
assert map_fetch(closed_map(a: integer()), :a) == {false, integer()}
270266

271-
{false, value_type} =
272-
open_map(my_map: open_map(foo: integer()))
273-
|> intersection(open_map(my_map: open_map(bar: boolean())))
274-
|> map_fetch(:my_map)
267+
assert map_fetch(union(closed_map(a: integer()), closed_map(b: atom())), :a) ==
268+
:badkey
275269

276-
assert equal?(value_type, open_map(foo: integer(), bar: boolean()))
270+
assert map_fetch(difference(closed_map(a: integer()), closed_map(a: term())), :a) ==
271+
:badkey
277272

278273
assert map_fetch(union(closed_map(a: integer()), closed_map(a: atom())), :a) ==
279274
{false, union(integer(), atom())}
280275

281-
assert map_fetch(union(closed_map(a: integer()), closed_map(b: atom())), :a) ==
282-
:badkey
276+
{false, value_type} =
277+
open_map(my_map: open_map(foo: integer()))
278+
|> intersection(open_map(my_map: open_map(bar: boolean())))
279+
|> map_fetch(:my_map)
283280

284-
assert map_fetch(difference(closed_map(a: integer()), closed_map(a: term())), :a) ==
285-
:badkey
281+
assert equal?(value_type, open_map(foo: integer(), bar: boolean()))
286282

287283
{false, value_type} =
288284
closed_map(a: union(integer(), atom()))
@@ -335,6 +331,21 @@ defmodule Module.Types.DescrTest do
335331
|> difference(open_map(a: atom([:foo, :baz])))
336332
|> map_fetch(:a) == {false, integer()}
337333
end
334+
335+
test "map_fetch with dynamic" do
336+
assert map_fetch(dynamic(), :a) == {true, dynamic()}
337+
338+
assert intersection(dynamic(), open_map(a: integer()))
339+
|> map_fetch(:a) == {false, intersection(integer(), dynamic())}
340+
341+
{false, type} = union(dynamic(integer()), open_map(a: integer())) |> map_fetch(:a)
342+
assert equal?(type, integer())
343+
344+
assert union(dynamic(integer()), open_map(a: if_set(integer()))) |> map_fetch(:a) == :badkey
345+
346+
assert union(dynamic(open_map(a: atom())), open_map(a: integer()))
347+
|> map_fetch(:a) == {false, union(dynamic(atom()), integer())}
348+
end
338349
end
339350

340351
describe "to_quoted" do

0 commit comments

Comments
 (0)