@@ -50,7 +50,7 @@ defmodule Module.Types.Descr do
50
50
def atom ( as ) , do: % { atom: atom_new ( as ) }
51
51
def atom ( ) , do: % { atom: @ atom_top }
52
52
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 )
54
54
def empty_list ( ) , do: % { bitmap: @ bit_empty_list }
55
55
def empty_map ( ) , do: % { map: @ map_empty }
56
56
def integer ( ) , do: % { bitmap: @ bit_integer }
@@ -59,7 +59,7 @@ defmodule Module.Types.Descr do
59
59
def list ( ) , do: % { bitmap: @ bit_list }
60
60
def non_empty_list ( ) , do: % { bitmap: @ bit_non_empty_list }
61
61
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 )
63
63
def pid ( ) , do: % { bitmap: @ bit_pid }
64
64
def port ( ) , do: % { bitmap: @ bit_port }
65
65
def reference ( ) , do: % { bitmap: @ bit_reference }
@@ -597,15 +597,34 @@ defmodule Module.Types.Descr do
597
597
# `%{..., a: if_set(not atom()), b: integer()}`. For maps with more keys,
598
598
# each key in a negated literal may create a new union when eliminated.
599
599
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
+
600
621
defp optional? ( % { bitmap: bitmap } ) when ( bitmap &&& @ bit_optional ) != 0 , do: true
601
622
defp optional? ( _ ) , do: false
602
623
603
624
defp map_tag_to_type ( :open ) , do: term_or_optional ( )
604
625
defp map_tag_to_type ( :closed ) , do: not_set ( )
605
626
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 , [ ] } ]
609
628
610
629
@ doc """
611
630
Fetches the type of the value returned by accessing `key` on `map`
@@ -834,8 +853,8 @@ defmodule Module.Types.Descr do
834
853
835
854
defp map_pop_key ( tag , fields , key ) do
836
855
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 ) } }
839
858
end
840
859
end
841
860
0 commit comments