@@ -283,7 +283,7 @@ defmodule Module.Types.Descr do
283283 case descr do
284284 % { dynamic: % { optional: 1 } } -> % { dynamic: % { optional: 1 } }
285285 % { optional: 1 } -> % { optional: 1 }
286- _ -> % { }
286+ _ -> @ none
287287 end
288288 end
289289
@@ -490,13 +490,21 @@ defmodule Module.Types.Descr do
490490
491491 defp iterator_difference_static ( :none , map ) , do: map
492492
493- defp empty_difference_static? ( left , :term ) , do: not Map . has_key? ( left , :optional )
493+ # This function is designed to compute the difference during subtyping efficiently.
494+ # Do not use it for anything else.
495+ defp empty_difference_subtype? ( % { dynamic: dyn_left } = left , % { dynamic: dyn_right } = right ) do
496+ # Dynamic will either exist on both sides or on none
497+ empty_difference_subtype? ( dyn_left , dyn_right ) and
498+ empty_difference_subtype? ( Map . delete ( left , :dynamic ) , Map . delete ( right , :dynamic ) )
499+ end
500+
501+ defp empty_difference_subtype? ( left , :term ) , do: keep_optional ( left ) == @ none
494502
495- defp empty_difference_static ?( left , right ) do
496- iterator_empty_difference_static ?( :maps . next ( :maps . iterator ( unfold ( left ) ) ) , unfold ( right ) )
503+ defp empty_difference_subtype ?( left , right ) do
504+ iterator_empty_difference_subtype ?( :maps . next ( :maps . iterator ( unfold ( left ) ) ) , unfold ( right ) )
497505 end
498506
499- defp iterator_empty_difference_static ?( { key , v1 , iterator } , map ) do
507+ defp iterator_empty_difference_subtype ?( { key , v1 , iterator } , map ) do
500508 case map do
501509 % { ^ key => v2 } ->
502510 value = difference ( key , v1 , v2 )
@@ -505,15 +513,14 @@ defmodule Module.Types.Descr do
505513 % { } ->
506514 empty_key? ( key , v1 )
507515 end and
508- iterator_empty_difference_static ?( :maps . next ( iterator ) , map )
516+ iterator_empty_difference_subtype ?( :maps . next ( iterator ) , map )
509517 end
510518
511- defp iterator_empty_difference_static ?( :none , _map ) , do: true
519+ defp iterator_empty_difference_subtype ?( :none , _map ) , do: true
512520
513521 # Returning 0 from the callback is taken as none() for that subtype.
514522 defp difference ( :atom , v1 , v2 ) , do: atom_difference ( v1 , v2 )
515523 defp difference ( :bitmap , v1 , v2 ) , do: v1 - ( v1 &&& v2 )
516- defp difference ( :dynamic , v1 , v2 ) , do: dynamic_difference ( v1 , v2 )
517524 defp difference ( :list , v1 , v2 ) , do: list_difference ( v1 , v2 )
518525 defp difference ( :map , v1 , v2 ) , do: map_difference ( v1 , v2 )
519526 defp difference ( :optional , 1 , 1 ) , do: 0
@@ -563,7 +570,6 @@ defmodule Module.Types.Descr do
563570 defp empty_key? ( :map , value ) , do: map_empty? ( value )
564571 defp empty_key? ( :list , value ) , do: list_empty? ( value )
565572 defp empty_key? ( :tuple , value ) , do: tuple_empty? ( value )
566- defp empty_key? ( :dynamic , value ) , do: empty? ( value )
567573 defp empty_key? ( _ , _value ) , do: false
568574
569575 @ doc """
@@ -690,7 +696,7 @@ defmodule Module.Types.Descr do
690696 end
691697
692698 defp subtype_static? ( same , same ) , do: true
693- defp subtype_static? ( left , right ) , do: empty_difference_static ?( left , right )
699+ defp subtype_static? ( left , right ) , do: empty_difference_subtype ?( left , right )
694700
695701 @ doc """
696702 Check if a type is equal to another.
@@ -2145,13 +2151,6 @@ defmodule Module.Types.Descr do
21452151 defp dynamic_intersection ( left , right ) ,
21462152 do: symmetrical_intersection ( unfold ( left ) , unfold ( right ) , & intersection / 3 )
21472153
2148- defp dynamic_difference ( left , right ) do
2149- case difference_static ( left , right ) do
2150- value when value == @ none -> 0
2151- value -> value
2152- end
2153- end
2154-
21552154 defp dynamic_to_quoted ( descr , opts ) do
21562155 cond do
21572156 descr == % { } ->
0 commit comments