@@ -1882,32 +1882,40 @@ defmodule Module.Types.Descr do
18821882 Checks if a list type is a proper list (terminated by empty list).
18831883 """
18841884 def list_proper? ( :term ) , do: false
1885- def list_proper? ( % { } = descr ) , do: Map . get ( descr , :dynamic , descr ) |> list_proper_static? ( )
18861885
1887- defp list_proper_static? ( :term ) , do: false
1886+ def list_proper? ( descr ) do
1887+ { dynamic , static } = Map . pop ( descr , :dynamic , descr )
18881888
1889- defp list_proper_static? ( % { } = descr ) do
18901889 # A list is proper if it's either the empty list alone, or all non-empty
1891- # list types have tails that are subtypes of empty list
1892- case descr do
1893- % { bitmap: bitmap , list: bdd } ->
1894- ( bitmap &&& @ bit_empty_list ) != 0 and empty? ( Map . drop ( descr , [ :list , :bitmap ] ) ) and
1895- list_bdd_proper? ( bdd )
1896-
1897- % { bitmap: bitmap } ->
1898- ( bitmap &&& @ bit_empty_list ) != 0 and empty? ( Map . delete ( descr , :bitmap ) )
1899-
1890+ # list types have tails that are subtypes of empty list.
1891+ case static do
19001892 % { list: bdd } ->
1901- empty? ( Map . delete ( descr , :list ) ) and list_bdd_proper? ( bdd )
1893+ Map . get ( static , :bitmap , @ bit_empty_list ) == @ bit_empty_list and
1894+ empty? ( Map . drop ( static , [ :list , :bitmap ] ) ) and
1895+ list_bdd_to_pos_dnf ( bdd )
1896+ |> Enum . all? ( fn { _list , last , _negs } -> subtype? ( last , @ empty_list ) end )
1897+
1898+ _ when static == % { bitmap: @ bit_empty_list } ->
1899+ true
19021900
19031901 % { } ->
1904- empty? ( descr )
1905- end
1906- end
1902+ # Dynamic requires only the empty list or a single proper list
1903+ empty? ( static ) and
1904+ case dynamic do
1905+ :term ->
1906+ true
19071907
1908- defp list_bdd_proper? ( bdd ) do
1909- list_bdd_to_pos_dnf ( bdd )
1910- |> Enum . all? ( fn { _list , last , _negs } -> subtype? ( last , @ empty_list ) end )
1908+ % { bitmap: bitmap } when ( bitmap &&& @ bit_empty_list ) != 0 ->
1909+ true
1910+
1911+ % { list: bdd } ->
1912+ list_bdd_to_pos_dnf ( bdd )
1913+ |> Enum . any? ( fn { _list , last , _negs } -> subtype? ( last , @ empty_list ) end )
1914+
1915+ % { } ->
1916+ false
1917+ end
1918+ end
19111919 end
19121920
19131921 defp list_intersection ( bdd_leaf ( list1 , last1 ) , bdd_leaf ( list2 , last2 ) ) do
0 commit comments