@@ -34,11 +34,11 @@ defmodule Module.Types.Pattern do
3434 defp args_to_previous ( types ) , do: args_to_static_domain ( types )
3535
3636 defp of_pattern_previous ( types , [ ] , _trees , _pattern_info , _tag , _stack , _context ) do
37- { :ok , types }
37+ { :ok , types , false }
3838 end
3939
4040 defp of_pattern_previous ( types , previous , trees , pattern_info , tag , stack , context ) do
41- types =
41+ refined_types =
4242 case types do
4343 [ type ] ->
4444 [ Enum . reduce ( previous , type , & difference ( & 2 , elem ( & 1 , 1 ) ) ) ]
@@ -54,7 +54,10 @@ defmodule Module.Types.Pattern do
5454 context = badpattern_error ( pattern , index , tag , stack , context )
5555 { :error , error_vars ( pattern_info , context ) }
5656 else
57- { :ok , types }
57+ # check_previous? is an optimization. If types have not changed,
58+ # it means args_types and previous are disjoint, and any further
59+ # refinement will keep them disjoint, so no need to check for previous.
60+ { :ok , refined_types , stack . mode != :infer and types != refined_types }
5861 end
5962 end
6063
@@ -190,18 +193,18 @@ defmodule Module.Types.Pattern do
190193 def of_head ( patterns , guards , expected , previous , tag , meta , stack , original ) do
191194 stack = % { stack | meta: meta }
192195
193- { trees , precise? , args_types , context } =
196+ { trees , precise? , check_previous? , args_types , context } =
194197 of_precise_head ( patterns , guards , expected , previous , tag , stack , original )
195198
196199 if context . failed and stack . mode != :infer and not empty_previous? ( previous ) and
197200 Keyword . get ( meta , :generated , false ) != true do
198201 # If it failed, let's try to break it down to a better error message.
199202 # First we check if it fails without previous, if it doesn't, check if it is redundant.
200203 case of_precise_head ( patterns , guards , expected , init_previous ( ) , tag , stack , original ) do
201- { other_trees , _ , _ , % { failed: true } = other_context } ->
204+ { other_trees , _ , _ , _ , % { failed: true } = other_context } ->
202205 { other_trees , previous , other_context }
203206
204- { other_trees , _ , args_types , other_context } ->
207+ { other_trees , _ , _ , args_types , other_context } ->
205208 if previous_subtype? ( args_types , previous ) do
206209 warning = { :redundant , tag , expected , args_types , previous , other_context }
207210 { other_trees , previous , warn ( __MODULE__ , warning , meta , stack , other_context ) }
@@ -211,7 +214,7 @@ defmodule Module.Types.Pattern do
211214 end
212215 else
213216 cond do
214- stack . mode != :infer and previous_subtype? ( args_types , previous ) ->
217+ check_previous? and previous_subtype? ( args_types , previous ) ->
215218 warning = { :redundant , tag , expected , args_types , previous , context }
216219 { trees , previous , warn ( __MODULE__ , warning , meta , stack , context ) }
217220
@@ -227,7 +230,7 @@ defmodule Module.Types.Pattern do
227230 defp of_precise_head ( [ ] , guards , _expected , _previous , _tag , stack , context ) do
228231 % { vars: vars } = context
229232 { guard_precise? , changed , context } = of_guards ( guards , vars , stack , context )
230- { [ ] , guard_precise? , [ ] , of_changed ( Map . keys ( changed ) , stack , context ) }
233+ { [ ] , guard_precise? , false , [ ] , of_changed ( Map . keys ( changed ) , stack , context ) }
231234 end
232235
233236 defp of_precise_head ( patterns , guards , expected , previous , tag , stack , context ) do
@@ -251,15 +254,15 @@ defmodule Module.Types.Pattern do
251254 else
252255 _ -> nil
253256 end ) ,
254- { :ok , types } <-
257+ { :ok , types , check_previous? } <-
255258 of_pattern_previous ( types , previous , trees , pattern_info , tag , stack , context ) ,
256259 { :ok , _types , context } <-
257260 of_pattern_refine ( types , changed , pattern_info , tag , stack , context ) do
258- { trees , pattern_precise? and guard_precise? ,
261+ { trees , pattern_precise? and guard_precise? , check_previous? ,
259262 args_types || trees_to_args_types ( trees , stack , context ) , context }
260263 else
261264 { :error , context } ->
262- { trees , false , trees_to_args_types ( trees , stack , context ) , context }
265+ { trees , false , false , trees_to_args_types ( trees , stack , context ) , context }
263266 end
264267 end
265268
0 commit comments