@@ -1844,38 +1844,23 @@ defmodule Module.Types.Descr do
18441844 acc
18451845
18461846 { list , last } ->
1847- if empty? ( list ) or empty? ( last ) do
1848- acc
1849- else
1850- Enum . reduce_while ( negs , { list_tail_unfold ( last ) , [ ] } , fn { neg_type , neg_last } ,
1851- { acc_last , acc_negs } ->
1852- if subtype? ( list , neg_type ) do
1853- difference = difference ( acc_last , neg_last )
1854- if empty? ( difference ) , do: { :halt , nil } , else: { :cont , { difference , acc_negs } }
1855- else
1856- { :cont , { acc_last , [ { neg_type , neg_last } | acc_negs ] } }
1857- end
1858- end )
1859- |> case do
1860- { :halt , nil } -> acc
1861- { last , negs } -> [ { list , last , Enum . reverse ( negs ) } | acc ]
1847+ Enum . reduce_while ( negs , { list_tail_unfold ( last ) , [ ] } , fn { neg_type , neg_last } ,
1848+ { acc_last , acc_negs } ->
1849+ if subtype? ( list , neg_type ) do
1850+ difference = difference ( acc_last , neg_last )
1851+ if empty? ( difference ) , do: { :halt , nil } , else: { :cont , { difference , acc_negs } }
1852+ else
1853+ { :cont , { acc_last , [ { neg_type , neg_last } | acc_negs ] } }
18621854 end
1855+ end )
1856+ |> case do
1857+ nil -> acc
1858+ { last , negs } -> [ { list , last , Enum . reverse ( negs ) } | acc ]
18631859 end
18641860 end
18651861 end )
18661862 end
18671863
1868- # Compute the head of a list (faster because we discard computations on the last type).
1869- defp list_bdd_to_hd ( bdd ) do
1870- bdd_to_dnf ( bdd )
1871- |> Enum . reduce ( none ( ) , fn { pos_list , neg_list } , acc ->
1872- case non_empty_list_literals_intersection ( pos_list ) do
1873- :empty -> acc
1874- { list , last } -> if list_line_empty? ( list , last , neg_list ) , do: acc , else: union ( acc , list )
1875- end
1876- end )
1877- end
1878-
18791864 defp list_pop_dynamic ( :term ) , do: { false , :term }
18801865
18811866 defp list_pop_dynamic ( descr ) do
@@ -1898,16 +1883,7 @@ defmodule Module.Types.Descr do
18981883 Checks if a list type is a proper list (terminated by empty list).
18991884 """
19001885 def list_proper? ( :term ) , do: false
1901-
1902- def list_proper? ( % { } = descr ) do
1903- case :maps . take ( :dynamic , descr ) do
1904- :error ->
1905- list_proper_static? ( descr )
1906-
1907- { dynamic , static } ->
1908- list_proper_static? ( static ) and ( list_proper_static? ( dynamic ) or empty? ( dynamic ) )
1909- end
1910- end
1886+ def list_proper? ( % { } = descr ) , do: Map . get ( descr , :dynamic , descr ) |> list_proper_static? ( )
19111887
19121888 defp list_proper_static? ( :term ) , do: false
19131889
@@ -1926,7 +1902,7 @@ defmodule Module.Types.Descr do
19261902 empty? ( Map . delete ( descr , :list ) ) and list_bdd_proper? ( bdd )
19271903
19281904 % { } ->
1929- false
1905+ empty? ( descr )
19301906 end
19311907 end
19321908
@@ -2045,20 +2021,19 @@ defmodule Module.Types.Descr do
20452021
20462022 defp list_hd_static ( :term ) , do: :term
20472023
2048- defp list_hd_static ( % { list: bdd } ) , do: list_bdd_to_hd ( bdd )
2024+ defp list_hd_static ( % { list: bdd } ) do
2025+ list_bdd_to_pos_dnf ( bdd )
2026+ |> Enum . reduce ( none ( ) , fn { list , _last , _negs } , acc -> union ( acc , list ) end )
2027+ end
20492028
20502029 defp list_hd_static ( % { } ) , do: none ( )
20512030
20522031 @ doc """
2053- Computes the type of the tail of a non-empty list type.
2054-
2055- Returns `{dynamic?, type}` on success, where `dynamic?` indicates whether
2056- the result contains a dynamic component. Returns `:badnonemptylist` if the
2057- input type is not guaranteed to be a non-empty list.
2032+ Returns the tail of a list.
20582033
2059- For a `non_empty_list(t)`, the tail type is `list(t)` (possibly empty) .
2034+ For a `non_empty_list(t)`, the tail type is `list(t)`.
20602035 For an improper list `non_empty_list(t, s)`, the tail type is
2061- `list(t, s) or s` (either the rest of the list or the terminator).
2036+ `list(t, s) or s` (either the rest of the list or the terminator)
20622037 """
20632038 def list_tl ( :term ) , do: :badnonemptylist
20642039
@@ -2097,8 +2072,7 @@ defmodule Module.Types.Descr do
20972072 end
20982073
20992074 list_bdd_to_pos_dnf ( bdd )
2100- |> Enum . reduce ( none ( ) , fn { _list , last , _negs } , acc -> union ( acc , last ) end )
2101- |> union ( initial )
2075+ |> Enum . reduce ( initial , fn { _list , last , _negs } , acc -> union ( acc , last ) end )
21022076 end
21032077
21042078 defp list_tl_static ( % { } ) , do: none ( )
@@ -2126,6 +2100,7 @@ defmodule Module.Types.Descr do
21262100 name = if empty? , do: :list , else: :non_empty_list
21272101 { name , [ to_quoted ( list_type , opts ) ] , empty? }
21282102
2103+ # Sugar: print the last type as term() if it only misses non empty lists.
21292104 subtype? ( @ not_non_empty_list , last_type ) ->
21302105 args = [ to_quoted ( list_type , opts ) , { :term , [ ] , [ ] } ]
21312106 { :non_empty_list , args , list_rendered? }
0 commit comments