@@ -354,15 +354,9 @@ 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
357+ defp of_pattern_var ( [ { :subpattern , key } | rest ] , type , context ) do
358+ % { ^ key => subpattern } = context . subpatterns
359+ of_pattern_var ( rest , intersection ( type , subpattern ) , context )
366360 end
367361
368362 defp of_pattern_var ( [ :tail | rest ] , type , context ) do
@@ -463,15 +457,6 @@ defmodule Module.Types.Pattern do
463457 { float ( ) , context }
464458 end
465459
466- @ doc """
467- Handle `size` in binary modifiers.
468-
469- They behave like guards, so we need to take into account their scope.
470- """
471- def of_size ( _match_or_guard , arg , expr , stack , context ) do
472- of_guard ( arg , integer ( ) , expr , stack , context )
473- end
474-
475460 ## Patterns
476461
477462 # :atom
@@ -543,16 +528,7 @@ defmodule Module.Types.Pattern do
543528 true -> { :intersection , [ Enum . reduce ( static , & intersection / 2 ) | dynamic ] }
544529 end
545530
546- # If the path has domain keys or head, then it is imprecise,
547- # and we need to keep filtering the match variable itself.
548- imprecise? =
549- Enum . any? ( path , fn
550- { :domain , _ } -> true
551- :head -> true
552- _ -> false
553- end )
554-
555- if dynamic == [ ] and not imprecise? do
531+ if dynamic == [ ] do
556532 { return , context }
557533 else
558534 context = of_var ( var , version , [ % { root: return , expr: match } ] , context )
@@ -714,7 +690,8 @@ defmodule Module.Types.Pattern do
714690 { key_type , context } = of_pattern ( key , [ % { root: :key , expr: key } ] , stack , context )
715691 true = is_descr ( key_type )
716692
717- { _value_type , context } = of_pattern ( value , [ { :domain , key_type } | path ] , stack , context )
693+ { _value_type , context } =
694+ of_subpattern ( value , [ { :domain , key_type } | path ] , stack , context )
718695
719696 # A domain key cannot restrict the map in any way,
720697 # because we are matching only on one possible value
@@ -757,18 +734,7 @@ defmodule Module.Types.Pattern do
757734
758735 result =
759736 Enum . reduce ( prefix , { [ ] , [ ] , context } , fn arg , { static , dynamic , 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
737+ { type , context } = of_subpattern ( arg , [ :head | path ] , stack , context )
772738
773739 if is_descr ( type ) do
774740 { [ type | static ] , dynamic , context }
@@ -789,6 +755,19 @@ defmodule Module.Types.Pattern do
789755 end
790756 end
791757
758+ # These cases don't need to store information because they have no intersection
759+ defp of_subpattern ( arg , path , stack , context )
760+ when is_number ( arg ) or is_binary ( arg ) or is_atom ( arg ) or arg == [ ] or is_var ( arg ) do
761+ of_pattern ( arg , path , stack , context )
762+ end
763+
764+ defp of_subpattern ( arg , path , stack , % { subpatterns: subpatterns } = context ) do
765+ key = map_size ( subpatterns )
766+ context = % { context | subpatterns: Map . put ( subpatterns , key , nil ) }
767+ { type , context } = of_pattern ( arg , [ { :subpattern , key } | path ] , stack , context )
768+ { type , put_in ( context . subpatterns [ key ] , of_pattern_tree ( type , context ) ) }
769+ end
770+
792771 ## Guards
793772 #
794773 # Whenever we have a or/orelse, we need to build multiple environments
0 commit comments