@@ -1854,38 +1854,23 @@ defmodule Module.Types.Descr do
18541854 acc
18551855
18561856 { list , last } ->
1857- if empty? ( list ) or empty? ( last ) do
1858- acc
1859- else
1860- Enum . reduce_while ( negs , { list_tail_unfold ( last ) , [ ] } , fn { neg_type , neg_last } ,
1861- { acc_last , acc_negs } ->
1862- if subtype? ( list , neg_type ) do
1863- difference = difference ( acc_last , neg_last )
1864- if empty? ( difference ) , do: { :halt , nil } , else: { :cont , { difference , acc_negs } }
1865- else
1866- { :cont , { acc_last , [ { neg_type , neg_last } | acc_negs ] } }
1867- end
1868- end )
1869- |> case do
1870- { :halt , nil } -> acc
1871- { last , negs } -> [ { list , last , Enum . reverse ( negs ) } | acc ]
1857+ Enum . reduce_while ( negs , { list_tail_unfold ( last ) , [ ] } , fn { neg_type , neg_last } ,
1858+ { acc_last , acc_negs } ->
1859+ if subtype? ( list , neg_type ) do
1860+ difference = difference ( acc_last , neg_last )
1861+ if empty? ( difference ) , do: { :halt , nil } , else: { :cont , { difference , acc_negs } }
1862+ else
1863+ { :cont , { acc_last , [ { neg_type , neg_last } | acc_negs ] } }
18721864 end
1865+ end )
1866+ |> case do
1867+ nil -> acc
1868+ { last , negs } -> [ { list , last , Enum . reverse ( negs ) } | acc ]
18731869 end
18741870 end
18751871 end )
18761872 end
18771873
1878- # Compute the head of a list (faster because we discard computations on the last type).
1879- defp list_bdd_to_hd ( bdd ) do
1880- bdd_to_dnf ( bdd )
1881- |> Enum . reduce ( none ( ) , fn { pos_list , neg_list } , acc ->
1882- case non_empty_list_literals_intersection ( pos_list ) do
1883- :empty -> acc
1884- { list , last } -> if list_line_empty? ( list , last , neg_list ) , do: acc , else: union ( acc , list )
1885- end
1886- end )
1887- end
1888-
18891874 defp list_pop_dynamic ( :term ) , do: { false , :term }
18901875
18911876 defp list_pop_dynamic ( descr ) do
@@ -1908,16 +1893,7 @@ defmodule Module.Types.Descr do
19081893 Checks if a list type is a proper list (terminated by empty list).
19091894 """
19101895 def list_proper? ( :term ) , do: false
1911-
1912- def list_proper? ( % { } = descr ) do
1913- case :maps . take ( :dynamic , descr ) do
1914- :error ->
1915- list_proper_static? ( descr )
1916-
1917- { dynamic , static } ->
1918- list_proper_static? ( static ) and ( list_proper_static? ( dynamic ) or empty? ( dynamic ) )
1919- end
1920- end
1896+ def list_proper? ( % { } = descr ) , do: Map . get ( descr , :dynamic , descr ) |> list_proper_static? ( )
19211897
19221898 defp list_proper_static? ( :term ) , do: false
19231899
@@ -1936,7 +1912,7 @@ defmodule Module.Types.Descr do
19361912 empty? ( Map . delete ( descr , :list ) ) and list_bdd_proper? ( bdd )
19371913
19381914 % { } ->
1939- false
1915+ empty? ( descr )
19401916 end
19411917 end
19421918
@@ -2055,20 +2031,19 @@ defmodule Module.Types.Descr do
20552031
20562032 defp list_hd_static ( :term ) , do: :term
20572033
2058- defp list_hd_static ( % { list: bdd } ) , do: list_bdd_to_hd ( bdd )
2034+ defp list_hd_static ( % { list: bdd } ) do
2035+ list_bdd_to_pos_dnf ( bdd )
2036+ |> Enum . reduce ( none ( ) , fn { list , _last , _negs } , acc -> union ( acc , list ) end )
2037+ end
20592038
20602039 defp list_hd_static ( % { } ) , do: none ( )
20612040
20622041 @ doc """
2063- Computes the type of the tail of a non-empty list type.
2064-
2065- Returns `{dynamic?, type}` on success, where `dynamic?` indicates whether
2066- the result contains a dynamic component. Returns `:badnonemptylist` if the
2067- input type is not guaranteed to be a non-empty list.
2042+ Returns the tail of a list.
20682043
2069- For a `non_empty_list(t)`, the tail type is `list(t)` (possibly empty) .
2044+ For a `non_empty_list(t)`, the tail type is `list(t)`.
20702045 For an improper list `non_empty_list(t, s)`, the tail type is
2071- `list(t, s) or s` (either the rest of the list or the terminator).
2046+ `list(t, s) or s` (either the rest of the list or the terminator)
20722047 """
20732048 def list_tl ( :term ) , do: :badnonemptylist
20742049
@@ -2107,8 +2082,7 @@ defmodule Module.Types.Descr do
21072082 end
21082083
21092084 list_bdd_to_pos_dnf ( bdd )
2110- |> Enum . reduce ( none ( ) , fn { _list , last , _negs } , acc -> union ( acc , last ) end )
2111- |> union ( initial )
2085+ |> Enum . reduce ( initial , fn { _list , last , _negs } , acc -> union ( acc , last ) end )
21122086 end
21132087
21142088 defp list_tl_static ( % { } ) , do: none ( )
@@ -2132,6 +2106,7 @@ defmodule Module.Types.Descr do
21322106 name = if empty? , do: :list , else: :non_empty_list
21332107 { name , [ to_quoted ( list_type , opts ) ] , empty? }
21342108
2109+ # Sugar: print the last type as term() if it only misses non empty lists.
21352110 subtype? ( @ not_non_empty_list , last_type ) ->
21362111 args = [ to_quoted ( list_type , opts ) , { :term , [ ] , [ ] } ]
21372112 { :non_empty_list , args , list_rendered? }
0 commit comments