@@ -2143,31 +2143,27 @@ defmodule Module.Types.Descr do
21432143 #
21442144 # none() types can be given and, while stored, it means the list type is empty.
21452145 defp list_descr ( list_type , last_type , empty? ) do
2146+ dynamic? = gradual? ( list_type ) or gradual? ( last_type )
21462147 { dynamic_list_type , static_list_type } = pop_dynamic ( list_type )
21472148 { dynamic_last_type , static_last_type } = pop_dynamic ( last_type )
2148- dynamic? = dynamic_list_type != static_list_type or dynamic_last_type != static_last_type
2149- static_possible? = not empty? ( static_list_type ) and not empty? ( static_last_type )
2150-
2151- dynamic_descr = list_descr_build ( dynamic_list_type , dynamic_last_type , empty? )
2149+ dynamic_descr = list_descr_static ( dynamic_list_type , dynamic_last_type , empty? )
2150+ # Just a syntactic check, to avoid a recursive empty? call
2151+ static_empty? = static_list_type == @ none or static_last_type == @ none
21522152
21532153 cond do
2154- empty? ( dynamic_descr ) ->
2155- % { }
2154+ not dynamic? ->
2155+ dynamic_descr
21562156
2157- dynamic? ->
2158- if not static_possible? do
2159- % { dynamic: dynamic_descr }
2160- else
2161- static_descr = list_descr_build ( static_list_type , static_last_type , empty? )
2162- Map . put ( static_descr , :dynamic , dynamic_descr )
2163- end
2157+ static_empty? ->
2158+ % { dynamic: dynamic_descr }
21642159
21652160 true ->
2166- dynamic_descr
2161+ list_descr_static ( static_list_type , static_last_type , empty? )
2162+ |> Map . put ( :dynamic , dynamic_descr )
21672163 end
21682164 end
21692165
2170- defp list_descr_build ( list_type , last_type , empty? ) do
2166+ defp list_descr_static ( list_type , last_type , empty? ) do
21712167 list_part =
21722168 if last_type == :term do
21732169 list_new ( :term , :term )
@@ -2791,29 +2787,19 @@ defmodule Module.Types.Descr do
27912787 defp domain_key_to_descr ( :list ) , do: @ list_top
27922788
27932789 defp map_descr ( tag , pairs ) do
2794- { fields , domains , dynamic_fields , dynamic_domains , dynamic? , static_possible ?} =
2795- map_descr_pairs ( pairs , [ ] , @ fields_new , [ ] , @ fields_new , false , true )
2790+ { fields , domains , dynamic_fields , dynamic_domains , dynamic? , static_empty ?} =
2791+ map_descr_pairs ( pairs )
27962792
2797- dynamic_descr = map_descr_build ( tag , dynamic_fields , dynamic_domains )
2793+ dynamic_descr = map_descr_static ( tag , dynamic_fields , dynamic_domains )
27982794
27992795 cond do
2800- empty? ( dynamic_descr ) ->
2801- % { }
2802-
2803- dynamic? ->
2804- if not static_possible? do
2805- % { dynamic: dynamic_descr }
2806- else
2807- static_descr = map_descr_build ( tag , fields , domains )
2808- Map . put ( static_descr , :dynamic , dynamic_descr )
2809- end
2810-
2811- true ->
2812- dynamic_descr
2796+ not dynamic? -> dynamic_descr
2797+ static_empty? -> % { dynamic: dynamic_descr }
2798+ true -> Map . put ( map_descr_static ( tag , fields , domains ) , :dynamic , dynamic_descr )
28132799 end
28142800 end
28152801
2816- defp map_descr_build ( tag , fields , domains ) do
2802+ defp map_descr_static ( tag , fields , domains ) do
28172803 map_new =
28182804 if not is_fields_empty ( domains ) do
28192805 domains =
@@ -2850,91 +2836,34 @@ defmodule Module.Types.Descr do
28502836
28512837 defp map_put_domain ( domain , [ ] , _initial , _value ) , do: domain
28522838
2853- defp map_descr_pairs (
2854- [ { key , :term } | rest ] ,
2855- fields ,
2856- domain ,
2857- dynamic_fields ,
2858- dynamic_domain ,
2859- dynamic? ,
2860- static_possible?
2861- ) do
2862- case is_atom ( key ) do
2863- true ->
2864- map_descr_pairs (
2865- rest ,
2866- [ { key , :term } | fields ] ,
2867- domain ,
2868- [ { key , :term } | dynamic_fields ] ,
2869- dynamic_domain ,
2870- dynamic? ,
2871- static_possible?
2872- )
2839+ defp map_descr_pairs ( pairs ) do
2840+ { fields , domains , dynamic_fields , dynamic_domains , dynamic? , static_possible? } =
2841+ Enum . reduce ( pairs , { [ ] , @ fields_new , [ ] , @ fields_new , false , false } , fn { key , value } , acc ->
2842+ map_descr_pair ( key , value , acc )
2843+ end )
28732844
2874- false ->
2875- map_descr_pairs (
2876- rest ,
2877- fields ,
2878- map_put_domain ( domain , key , :term ) ,
2879- dynamic_fields ,
2880- map_put_domain ( dynamic_domain , key , :term ) ,
2881- dynamic? ,
2882- static_possible?
2883- )
2884- end
2845+ { fields_from_reverse_list ( fields ) , domains , fields_from_reverse_list ( dynamic_fields ) ,
2846+ dynamic_domains , dynamic? , static_possible? }
28852847 end
28862848
2887- defp map_descr_pairs (
2888- [ { key , value } | rest ] ,
2889- fields ,
2890- domain ,
2891- dynamic_fields ,
2892- dynamic_domain ,
2893- dynamic? ,
2894- static_possible?
2849+ defp map_descr_pair (
2850+ key ,
2851+ value ,
2852+ { fields , domains , dynamic_fields , dynamic_domains , dynamic? , static_empty? }
28952853 ) do
28962854 { dynamic_value , static_value } = pop_dynamic ( value )
2897- dynamic? = dynamic? or dynamic_value != static_value
2898- static_possible ? = static_possible? and not empty? ( static_value )
2855+ dynamic? = dynamic? or gradual? ( value )
2856+ static_empty ? = static_empty? or static_value == @ none
28992857
2900- case is_atom ( key ) do
2901- true ->
2902- map_descr_pairs (
2903- rest ,
2904- [ { key , static_value } | fields ] ,
2905- domain ,
2906- [ { key , dynamic_value } | dynamic_fields ] ,
2907- dynamic_domain ,
2908- dynamic? ,
2909- static_possible?
2910- )
2911-
2912- false ->
2913- map_descr_pairs (
2914- rest ,
2915- fields ,
2916- map_put_domain ( domain , key , static_value ) ,
2917- dynamic_fields ,
2918- map_put_domain ( dynamic_domain , key , dynamic_value ) ,
2919- dynamic? ,
2920- static_possible?
2921- )
2858+ if is_atom ( key ) do
2859+ { [ { key , static_value } | fields ] , domains , [ { key , dynamic_value } | dynamic_fields ] ,
2860+ dynamic_domains , dynamic? , static_empty? }
2861+ else
2862+ { fields , map_put_domain ( domains , key , static_value ) , dynamic_fields ,
2863+ map_put_domain ( dynamic_domains , key , dynamic_value ) , dynamic? , static_empty? }
29222864 end
29232865 end
29242866
2925- defp map_descr_pairs (
2926- [ ] ,
2927- fields ,
2928- domain ,
2929- dynamic_fields ,
2930- dynamic_domain ,
2931- dynamic? ,
2932- static_possible?
2933- ) do
2934- { fields_from_reverse_list ( fields ) , domain , fields_from_reverse_list ( dynamic_fields ) ,
2935- dynamic_domain , dynamic? , static_possible? }
2936- end
2937-
29382867 # Gets the default type associated to atom keys in a map.
29392868 defp map_key_tag_to_type ( :open ) , do: term_or_optional ( )
29402869 defp map_key_tag_to_type ( :closed ) , do: not_set ( )
@@ -4981,47 +4910,34 @@ defmodule Module.Types.Descr do
49814910 # - {atom(), boolean(), ...} is encoded as {:open, [atom(), boolean()]}
49824911
49834912 defp tuple_descr ( tag , fields ) do
4984- case tuple_descr ( fields , [ ] , [ ] , false , true ) do
4985- :empty ->
4986- % { }
4913+ { static_fields , dynamic_fields , dynamic? , static_empty? } =
4914+ tuple_descr_fields ( fields , [ ] , [ ] , false , false )
49874915
4988- { static_fields , dynamic_fields , true , static_possible? } ->
4989- dynamic_descr = % { tuple: tuple_new ( tag , :lists . reverse ( dynamic_fields ) ) }
4916+ dynamic_descr = tuple_descr_static ( tag , dynamic_fields )
49904917
4991- if not static_possible? do
4992- % { dynamic: dynamic_descr }
4993- else
4994- static_descr = % { tuple: tuple_new ( tag , :lists . reverse ( static_fields ) ) }
4995- Map . put ( static_descr , :dynamic , dynamic_descr )
4996- end
4997-
4998- { fields , _dynamic_fields , false , _static_possible? } ->
4999- % { tuple: tuple_new ( tag , :lists . reverse ( fields ) ) }
4918+ cond do
4919+ not dynamic? -> dynamic_descr
4920+ static_empty? -> % { dynamic: dynamic_descr }
4921+ true -> Map . put ( tuple_descr_static ( tag , static_fields ) , :dynamic , dynamic_descr )
50004922 end
50014923 end
50024924
5003- defp tuple_descr ( [ :term | rest ] , acc , dynamic_acc , dynamic? , static_possible? ) do
5004- tuple_descr ( rest , [ :term | acc ] , [ :term | dynamic_acc ] , dynamic? , static_possible? )
5005- end
4925+ defp tuple_descr_static ( tag , fields ) , do: % { tuple: tuple_new ( tag , :lists . reverse ( fields ) ) }
50064926
5007- defp tuple_descr ( [ value | rest ] , acc , dynamic_acc , dynamic? , static_possible ?) do
4927+ defp tuple_descr_fields ( [ value | rest ] , acc , dynamic_acc , dynamic? , static_empty ?) do
50084928 { dynamic_value , static_value } = pop_dynamic ( value )
50094929
5010- if empty? ( dynamic_value ) do
5011- :empty
5012- else
5013- tuple_descr (
5014- rest ,
5015- [ static_value | acc ] ,
5016- [ dynamic_value | dynamic_acc ] ,
5017- dynamic? or dynamic_value != static_value ,
5018- static_possible? and not empty? ( static_value )
5019- )
5020- end
4930+ tuple_descr_fields (
4931+ rest ,
4932+ [ static_value | acc ] ,
4933+ [ dynamic_value | dynamic_acc ] ,
4934+ dynamic? or gradual? ( value ) ,
4935+ static_empty? or static_value == @ none
4936+ )
50214937 end
50224938
5023- defp tuple_descr ( [ ] , acc , dynamic_acc , dynamic? , static_possible ?) do
5024- { acc , dynamic_acc , dynamic? , static_possible ?}
4939+ defp tuple_descr_fields ( [ ] , acc , dynamic_acc , dynamic? , static_empty ?) do
4940+ { acc , dynamic_acc , dynamic? , static_empty ?}
50254941 end
50264942
50274943 defp tuple_new ( tag , elements ) , do: bdd_leaf_new ( tag , elements )
@@ -5040,7 +4956,14 @@ defmodule Module.Types.Descr do
50404956 end
50414957 end
50424958
5043- defp tuple_literal_intersection ( :open , [ ] , tag , elements ) , do: { tag , elements }
4959+ # Detecting tuples built with none() fields
4960+ defp tuple_literal_intersection ( :open , [ ] , tag , elements ) do
4961+ if Enum . any? ( elements , & empty? / 1 ) do
4962+ :empty
4963+ else
4964+ { tag , elements }
4965+ end
4966+ end
50444967
50454968 defp tuple_literal_intersection ( tag1 , elements1 , tag2 , elements2 ) do
50464969 case tuple_sizes_strategy ( tag1 , length ( elements1 ) , tag2 , length ( elements2 ) ) do
@@ -5679,7 +5602,7 @@ defmodule Module.Types.Descr do
56795602 def tuple_values ( descr ) do
56805603 case :maps . take ( :dynamic , descr ) do
56815604 :error ->
5682- if tuple_only ?( descr ) do
5605+ if non_empty_tuple_only ?( descr ) do
56835606 process_tuples_values ( Map . get ( descr , :tuple , :bdd_bot ) )
56845607 else
56855608 :badtuple
@@ -5725,7 +5648,7 @@ defmodule Module.Types.Descr do
57255648 case :maps . take ( :dynamic , descr ) do
57265649 :error ->
57275650 # Note: the empty type is not a valid input
5728- is_proper_tuple? = descr_key? ( descr , :tuple ) and tuple_only ?( descr )
5651+ is_proper_tuple? = descr_key? ( descr , :tuple ) and non_empty_tuple_only ?( descr )
57295652 is_proper_size? = tuple_of_size_at_least_static? ( descr , index + 1 )
57305653
57315654 cond do
@@ -5794,7 +5717,7 @@ defmodule Module.Types.Descr do
57945717 case :maps . take ( :dynamic , descr ) do
57955718 :error ->
57965719 # Note: the empty type is not a valid input
5797- is_proper_tuple? = descr_key? ( descr , :tuple ) and tuple_only ?( descr )
5720+ is_proper_tuple? = descr_key? ( descr , :tuple ) and non_empty_tuple_only ?( descr )
57985721 is_proper_size? = index == 0 or tuple_of_size_at_least_static? ( descr , index )
57995722
58005723 cond do
0 commit comments