@@ -8,6 +8,63 @@ defmodule Module.Types.Pattern do
88 alias Module.Types . { Apply , Of }
99 import Module.Types . { Helpers , Descr }
1010
11+ @ doc """
12+ Returns the initial value for previous clause information.
13+ """
14+ def init_previous do
15+ { [ ] , none ( ) }
16+ end
17+
18+ defp empty_previous? ( { list , _descr } ) , do: list == [ ]
19+
20+ defp previous_subtype? ( _ , { [ ] , _ } ) , do: false
21+ defp previous_subtype? ( [ ] , _ ) , do: true
22+ defp previous_subtype? ( [ type ] , { _ , descr } ) , do: subtype? ( type , descr )
23+ defp previous_subtype? ( args , { _ , descr } ) , do: subtype? ( args_to_domain ( args ) , descr )
24+
25+ defp concat_previous ( [ ] , previous ) ,
26+ do: previous
27+
28+ defp concat_previous ( [ type ] , { list , descr } ) ,
29+ do: { [ [ type ] | list ] , union ( type , descr ) }
30+
31+ defp concat_previous ( types , { list , descr } ) ,
32+ do: { [ types | list ] , union ( args_to_domain ( types ) , descr ) }
33+
34+ defp of_pattern_previous ( types , { [ ] , _ } , _trees , _pattern_info , _tag , _stack , _context ) do
35+ { :ok , types }
36+ end
37+
38+ defp of_pattern_previous ( types , { _ , descr } , trees , pattern_info , tag , stack , context ) do
39+ types =
40+ case types do
41+ [ type ] ->
42+ [ difference ( type , descr ) ]
43+
44+ [ _ | _ ] ->
45+ types
46+ |> args_to_domain ( )
47+ |> difference ( descr )
48+ |> domain_to_flat_args ( types )
49+ end
50+
51+ if index = Enum . find_index ( types , & empty? / 1 ) do
52+ { _ , _ , pattern } = Enum . fetch! ( trees , index )
53+ context = badpattern_error ( pattern , index , tag , stack , context )
54+ { :error , error_vars ( pattern_info , context ) }
55+ else
56+ { :ok , types }
57+ end
58+ end
59+
60+ defp previous_to_string ( { previous , _ } ) do
61+ Enum . map_join ( previous , "\n " , fn types ->
62+ types
63+ |> Enum . map_join ( ", " , & to_quoted_string / 1 )
64+ |> indent ( 4 )
65+ end )
66+ end
67+
1168 @ doc """
1269 Refine the dependencies of variables represented by version.
1370 """
@@ -129,16 +186,17 @@ defmodule Module.Types.Pattern do
129186 Every step we deduct previous clauses from the current ones and,
130187 in case of failures, we try to break down the root cause.
131188 """
132- def of_head ( patterns , guards , expected , previous , tag , meta , stack , original_context ) do
189+ def of_head ( patterns , guards , expected , previous , tag , meta , stack , original ) do
133190 stack = % { stack | meta: meta }
134191
135192 { trees , precise? , context } =
136- of_precise_head ( patterns , guards , expected , previous , tag , stack , original_context )
193+ of_precise_head ( patterns , guards , expected , previous , tag , stack , original )
137194
138- if context . failed and previous != [ ] and Keyword . get ( meta , :generated , false ) != true do
195+ if context . failed and not empty_previous? ( previous ) and
196+ Keyword . get ( meta , :generated , false ) != true do
139197 # If it failed, let's try to break it down to a better error message.
140198 # First we check if it fails without previous, if it doesn't, check if it is redundant.
141- case of_precise_head ( patterns , guards , expected , [ ] , tag , stack , original_context ) do
199+ case of_precise_head ( patterns , guards , expected , init_previous ( ) , tag , stack , original ) do
142200 { other_trees , _ , % { failed: true } = other_context } ->
143201 { other_trees , previous , other_context }
144202
@@ -150,7 +208,7 @@ defmodule Module.Types.Pattern do
150208 |> upper_bound ( )
151209 end )
152210
153- if args_subtype ?( args_types , previous ) do
211+ if previous_subtype ?( args_types , previous ) do
154212 warning = { :redundant , tag , expected , args_types , previous , other_context }
155213 { other_trees , previous , warn ( __MODULE__ , warning , meta , stack , other_context ) }
156214 else
@@ -166,12 +224,12 @@ defmodule Module.Types.Pattern do
166224 end )
167225
168226 cond do
169- args_subtype ?( args_types , previous ) ->
227+ previous_subtype ?( args_types , previous ) ->
170228 warning = { :redundant , tag , expected , args_types , previous , context }
171229 { trees , previous , warn ( __MODULE__ , warning , meta , stack , context ) }
172230
173231 precise? ->
174- { trees , [ args_types | previous ] , context }
232+ { trees , concat_previous ( args_types , previous ) , context }
175233
176234 true ->
177235 { trees , previous , context }
@@ -192,22 +250,6 @@ defmodule Module.Types.Pattern do
192250 end
193251 end
194252
195- defp args_subtype? ( _ , [ ] ) ,
196- do: false
197-
198- defp args_subtype? ( [ ] , _ ) ,
199- do: true
200-
201- defp args_subtype? ( [ type ] , previous ) ,
202- do: subtype? ( type , Enum . reduce ( previous , none ( ) , & union ( & 2 , hd ( & 1 ) ) ) )
203-
204- defp args_subtype? ( args , previous ) do
205- subtype? (
206- args_to_domain ( args ) ,
207- Enum . reduce ( previous , none ( ) , & union ( & 2 , args_to_domain ( & 1 ) ) )
208- )
209- end
210-
211253 @ doc """
212254 Computes the domain from the pattern tree and expected types.
213255
@@ -335,31 +377,6 @@ defmodule Module.Types.Pattern do
335377 { :ok , Enum . reverse ( acc ) }
336378 end
337379
338- defp of_pattern_previous ( types , [ ] , _trees , _pattern_info , _tag , _stack , _context ) do
339- { :ok , types }
340- end
341-
342- defp of_pattern_previous ( types , previous , trees , pattern_info , tag , stack , context ) do
343- types =
344- case types do
345- [ type ] ->
346- [ Enum . reduce ( previous , type , & difference ( & 2 , hd ( & 1 ) ) ) ]
347-
348- [ _ | _ ] ->
349- previous
350- |> Enum . reduce ( args_to_domain ( types ) , & difference ( & 2 , args_to_domain ( & 1 ) ) )
351- |> domain_to_flat_args ( types )
352- end
353-
354- if index = Enum . find_index ( types , & empty? / 1 ) do
355- { _ , _ , pattern } = Enum . fetch! ( trees , index )
356- context = badpattern_error ( pattern , index , tag , stack , context )
357- { :error , error_vars ( pattern_info , context ) }
358- else
359- { :ok , types }
360- end
361- end
362-
363380 defp of_pattern_refine ( types , pattern_info , tag , stack , context ) do
364381 pattern_info
365382 |> Enum . reverse ( )
@@ -1490,7 +1507,7 @@ defmodule Module.Types.Pattern do
14901507 else
14911508 _ ->
14921509 with { _op , _meta , expr , type } <- info ,
1493- true <- args_subtype ?( expected , previous ) do
1510+ true <- previous_subtype ?( expected , previous ) do
14941511 """
14951512 the following clause cannot match because the previous clauses already matched all possible values:
14961513
@@ -1690,12 +1707,4 @@ defmodule Module.Types.Pattern do
16901707 |> Enum . map_join ( ", " , & to_quoted_string / 1 )
16911708 |> indent ( 4 )
16921709 end
1693-
1694- defp previous_to_string ( previous ) do
1695- Enum . map_join ( previous , "\n " , fn types ->
1696- types
1697- |> Enum . map_join ( ", " , & to_quoted_string / 1 )
1698- |> indent ( 4 )
1699- end )
1700- end
17011710end
0 commit comments