@@ -230,8 +230,8 @@ defmodule Module.Types.Pattern do
230230
231231 defp of_precise_head ( [ ] , guards , _expected , _previous , _tag , stack , context ) do
232232 % { vars: vars } = context
233- { guard_precise? , changed , context } = of_guards ( guards , [ ] , vars , stack , context )
234- { [ ] , guard_precise? , [ ] , of_changed ( changed , stack , context ) }
233+ { guard_precise? , changed , context } = of_guards ( guards , vars , stack , context )
234+ { [ ] , guard_precise? , [ ] , of_changed ( Map . keys ( changed ) , stack , context ) }
235235 end
236236
237237 defp of_precise_head ( patterns , guards , expected , previous , tag , stack , context ) do
@@ -242,52 +242,39 @@ defmodule Module.Types.Pattern do
242242 of_pattern_args_zip ( patterns , expected , 0 , [ ] , true , stack , context )
243243
244244 { pattern_info , context } = pop_pattern_info ( context )
245- { guard_precise? , changed , context } = of_guards ( guards , [ ] , vars , stack , context )
245+ { guard_precise? , changed , context } = of_guards ( guards , vars , stack , context )
246246
247247 with { :ok , types } <-
248248 of_pattern_intersect ( trees , 0 , [ ] , pattern_info , tag , stack , context ) ,
249- fork_types = types ,
250- fork_context = context ,
251- fork_changed = changed ,
249+ # We compute the args types before we do the intersection with previous clauses
250+ args_types =
251+ ( with [ _ | _ ] <- previous ,
252+ { :ok , _types , context } <-
253+ of_pattern_refine ( types , changed , pattern_info , tag , stack , context ) do
254+ trees_to_args_types ( trees , stack , context )
255+ else
256+ _ -> nil
257+ end ) ,
252258 { :ok , types } <-
253259 of_pattern_previous ( types , previous , trees , pattern_info , tag , stack , context ) ,
254- { _types , changed , context } <-
260+ { :ok , _types , context } <-
255261 of_pattern_refine ( types , changed , pattern_info , tag , stack , context ) do
256- args_types =
257- if previous != [ ] do
258- { _types , fork_changed , fork_context } =
259- of_pattern_refine ( fork_types , fork_changed , pattern_info , tag , stack , fork_context )
260-
261- fork_context = of_changed ( fork_changed , stack , fork_context )
262-
263- Enum . map ( trees , fn { tree , _ , _ } ->
264- tree
265- |> of_pattern_tree ( stack , fork_context )
266- |> upper_bound ( )
267- end )
268- else
269- Enum . map ( trees , fn { tree , _ , _ } ->
270- tree
271- |> of_pattern_tree ( stack , context )
272- |> upper_bound ( )
273- end )
274- end
275-
276- { trees , pattern_precise? and guard_precise? , args_types ,
277- of_changed ( changed , stack , context ) }
262+ { trees , pattern_precise? and guard_precise? ,
263+ args_types || trees_to_args_types ( trees , stack , context ) , context }
278264 else
279265 { :error , context } ->
280- args_types =
281- Enum . map ( trees , fn { tree , _ , _ } ->
282- tree
283- |> of_pattern_tree ( stack , context )
284- |> upper_bound ( )
285- end )
286-
287- { trees , false , args_types , context }
266+ { trees , false , trees_to_args_types ( trees , stack , context ) , context }
288267 end
289268 end
290269
270+ defp trees_to_args_types ( trees , stack , context ) do
271+ Enum . map ( trees , fn { tree , _ , _ } ->
272+ tree
273+ |> of_pattern_tree ( stack , context )
274+ |> upper_bound ( )
275+ end )
276+ end
277+
291278 @ doc """
292279 Computes the domain from the pattern tree and expected types.
293280
@@ -342,9 +329,9 @@ defmodule Module.Types.Pattern do
342329
343330 with { :ok , types } <-
344331 of_pattern_intersect ( args , 0 , [ ] , pattern_info , tag , stack , context ) ,
345- { [ type ] , changed , context } <-
346- of_pattern_refine ( types , pattern_info , tag , stack , context ) do
347- { type , of_changed ( changed , stack , context ) }
332+ { :ok , [ type ] , context } <-
333+ of_pattern_refine ( types , % { } , pattern_info , tag , stack , context ) do
334+ { type , context }
348335 else
349336 { :error , context } -> { expected , context }
350337 end
@@ -361,16 +348,13 @@ defmodule Module.Types.Pattern do
361348
362349 { pattern_info , context } = pop_pattern_info ( context )
363350 args = [ { tree , expected , pattern } ]
351+ { _precise? , changed , context } = of_guards ( guards , vars , stack , context )
364352
365- with { :ok , types } <- of_pattern_intersect ( args , 0 , [ ] , pattern_info , tag , stack , context ) do
366- { _precise? , changed , context } = of_guards ( guards , [ ] , vars , stack , context )
367-
368- with { _types , changed , context } <-
369- of_pattern_refine ( types , changed , pattern_info , tag , stack , context ) do
370- of_changed ( changed , stack , context )
371- else
372- { :error , context } -> context
373- end
353+ with { :ok , types } <-
354+ of_pattern_intersect ( args , 0 , [ ] , pattern_info , tag , stack , context ) ,
355+ { :ok , _types , context } <-
356+ of_pattern_refine ( types , changed , pattern_info , tag , stack , context ) do
357+ context
374358 else
375359 { :error , context } -> context
376360 end
@@ -394,7 +378,7 @@ defmodule Module.Types.Pattern do
394378 { :ok , Enum . reverse ( acc ) }
395379 end
396380
397- defp of_pattern_refine ( types , changed \\ [ ] , pattern_info , tag , stack , context ) do
381+ defp of_pattern_refine ( types , changed , pattern_info , tag , stack , context ) do
398382 pattern_info
399383 |> Enum . reverse ( )
400384 |> Enum . reduce ( { changed , context } , fn { version , _pinned , node } , { changed , context } ->
@@ -425,13 +409,13 @@ defmodule Module.Types.Pattern do
425409 throw ( badpattern_error ( expr , index , tag , stack , context ) )
426410 end
427411
428- { [ version | changed ] , context }
412+ { Map . put ( changed , version , true ) , context }
429413 end )
430414 catch
431415 context -> { :error , error_vars ( pattern_info , context ) }
432416 else
433417 { changed , context } ->
434- { types , changed , context }
418+ { :ok , types , of_changed ( Map . keys ( changed ) , stack , context ) }
435419 end
436420
437421 defp error_vars ( pattern_info , context ) do
@@ -531,13 +515,11 @@ defmodule Module.Types.Pattern do
531515 end
532516 end
533517
534- @ doc """
535- Receives the pattern tree and the context and returns a concrete type.
536- """
537- def of_pattern_tree ( descr , _stack , _context ) when is_descr ( descr ) ,
518+ # Receives the pattern tree and the context and returns a concrete type.
519+ defp of_pattern_tree ( descr , _stack , _context ) when is_descr ( descr ) ,
538520 do: descr
539521
540- def of_pattern_tree ( { :guard , name , polarity , guard , expr } , stack , context ) do
522+ defp of_pattern_tree ( { :guard , name , polarity , guard , expr } , stack , context ) do
541523 { type , _context } = of_guard ( guard , term ( ) , expr , stack , context )
542524
543525 # This logic mirrors the code in `Apply.compare`
@@ -553,25 +535,25 @@ defmodule Module.Types.Pattern do
553535 end
554536 end
555537
556- def of_pattern_tree ( { :tuple , entries } , stack , context ) do
538+ defp of_pattern_tree ( { :tuple , entries } , stack , context ) do
557539 tuple ( Enum . map ( entries , & of_pattern_tree ( & 1 , stack , context ) ) )
558540 end
559541
560- def of_pattern_tree ( { :open_map , static , dynamic } , stack , context ) do
542+ defp of_pattern_tree ( { :open_map , static , dynamic } , stack , context ) do
561543 dynamic =
562544 Enum . map ( dynamic , fn { key , value } -> { key , of_pattern_tree ( value , stack , context ) } end )
563545
564546 open_map ( static ++ dynamic )
565547 end
566548
567- def of_pattern_tree ( { :closed_map , static , dynamic } , stack , context ) do
549+ defp of_pattern_tree ( { :closed_map , static , dynamic } , stack , context ) do
568550 dynamic =
569551 Enum . map ( dynamic , fn { key , value } -> { key , of_pattern_tree ( value , stack , context ) } end )
570552
571553 closed_map ( static ++ dynamic )
572554 end
573555
574- def of_pattern_tree ( { :non_empty_list , [ head | tail ] , suffix } , stack , context ) do
556+ defp of_pattern_tree ( { :non_empty_list , [ head | tail ] , suffix } , stack , context ) do
575557 tail
576558 |> Enum . reduce (
577559 of_pattern_tree ( head , stack , context ) ,
@@ -580,20 +562,20 @@ defmodule Module.Types.Pattern do
580562 |> non_empty_list ( of_pattern_tree ( suffix , stack , context ) )
581563 end
582564
583- def of_pattern_tree ( { :intersection , entries } , stack , context ) do
565+ defp of_pattern_tree ( { :intersection , entries } , stack , context ) do
584566 entries
585567 |> Enum . map ( & of_pattern_tree ( & 1 , stack , context ) )
586568 |> Enum . reduce ( & intersection / 2 )
587569 end
588570
589- def of_pattern_tree ( { :var , version } , _stack , context ) do
571+ defp of_pattern_tree ( { :var , version } , _stack , context ) do
590572 case context do
591573 % { vars: % { ^ version => % { type: type } } } -> type
592574 _ -> term ( )
593575 end
594576 end
595577
596- def of_pattern_tree ( :key , _stack , _context ) do
578+ defp of_pattern_tree ( :key , _stack , _context ) do
597579 term ( )
598580 end
599581
@@ -1037,22 +1019,22 @@ defmodule Module.Types.Pattern do
10371019 @ atom_true atom ( [ true ] )
10381020 @ atom_false atom ( [ false ] )
10391021
1040- defp of_guards ( [ ] , changed , _vars , _stack , context ) do
1041- { true , changed , context }
1022+ defp of_guards ( [ ] , _vars , _stack , context ) do
1023+ { true , % { } , context }
10421024 end
10431025
1044- defp of_guards ( guards , changed , vars , stack , context ) do
1026+ defp of_guards ( guards , vars , stack , context ) do
10451027 context =
10461028 init_pattern_info ( context , % {
10471029 allow_empty?: false ,
10481030 parent_version: nil ,
10491031 vars: vars ,
1050- changed: Map . from_keys ( changed , [ ] )
1032+ changed: % { }
10511033 } )
10521034
10531035 { precise? , context } = of_guards ( guards , stack , context )
10541036 { % { vars: vars , changed: changed } , context } = pop_pattern_info ( context )
1055- { is_map ( vars ) and precise? , Map . keys ( changed ) , context }
1037+ { is_map ( vars ) and precise? , changed , context }
10561038 end
10571039
10581040 defp of_guards ( [ guard ] , stack , context ) do
0 commit comments