@@ -354,6 +354,17 @@ defmodule Module.Types.Pattern do
354354 end
355355 end
356356
357+ defp of_pattern_var ( [ { :head , key } | rest ] , type , context ) do
358+ case list_hd ( type ) do
359+ { :ok , head } ->
360+ % { ^ key => tree } = context . heads
361+ of_pattern_var ( rest , intersection ( head , of_pattern_tree ( tree , context ) ) , context )
362+
363+ _ ->
364+ :error
365+ end
366+ end
367+
357368 defp of_pattern_var ( [ :tail | rest ] , type , context ) do
358369 case list_tl ( type ) do
359370 { :ok , tail } -> of_pattern_var ( rest , tail , context )
@@ -746,7 +757,18 @@ defmodule Module.Types.Pattern do
746757
747758 result =
748759 Enum . reduce ( prefix , { [ ] , [ ] , context } , fn arg , { static , dynamic , context } ->
749- { type , context } = of_pattern ( arg , [ :head | path ] , stack , context )
760+ # These cases don't need to store head information because
761+ # they have no intersection
762+ { type , context } =
763+ if is_number ( arg ) or is_binary ( arg ) or is_atom ( arg ) or arg == [ ] or is_var ( arg ) do
764+ of_pattern ( arg , [ :head | path ] , stack , context )
765+ else
766+ % { heads: heads } = context
767+ key = map_size ( heads )
768+ context = % { context | heads: Map . put ( heads , key , nil ) }
769+ { type , context } = of_pattern ( arg , [ { :head , key } | path ] , stack , context )
770+ { type , put_in ( context . heads [ key ] , type ) }
771+ end
750772
751773 if is_descr ( type ) do
752774 { [ type | static ] , dynamic , context }
0 commit comments