@@ -257,7 +257,7 @@ defmodule Module.Types.Descr do
257257 case descr do
258258 % { dynamic: % { optional: 1 } } -> % { dynamic: % { optional: 1 } }
259259 % { optional: 1 } -> % { optional: 1 }
260- _ -> % { }
260+ _ -> @ none
261261 end
262262 end
263263
@@ -464,13 +464,21 @@ defmodule Module.Types.Descr do
464464
465465 defp iterator_difference_static ( :none , map ) , do: map
466466
467- defp empty_difference_static? ( left , :term ) , do: not Map . has_key? ( left , :optional )
467+ # This function is designed to compute the difference during subtyping efficiently.
468+ # Do not use it for anything else.
469+ defp empty_difference_subtype? ( % { dynamic: dyn_left } = left , % { dynamic: dyn_right } = right ) do
470+ # Dynamic will either exist on both sides or on none
471+ empty_difference_subtype? ( dyn_left , dyn_right ) and
472+ empty_difference_subtype? ( Map . delete ( left , :dynamic ) , Map . delete ( right , :dynamic ) )
473+ end
474+
475+ defp empty_difference_subtype? ( left , :term ) , do: keep_optional ( left ) == @ none
468476
469- defp empty_difference_static ?( left , right ) do
470- iterator_empty_difference_static ?( :maps . next ( :maps . iterator ( unfold ( left ) ) ) , unfold ( right ) )
477+ defp empty_difference_subtype ?( left , right ) do
478+ iterator_empty_difference_subtype ?( :maps . next ( :maps . iterator ( unfold ( left ) ) ) , unfold ( right ) )
471479 end
472480
473- defp iterator_empty_difference_static ?( { key , v1 , iterator } , map ) do
481+ defp iterator_empty_difference_subtype ?( { key , v1 , iterator } , map ) do
474482 case map do
475483 % { ^ key => v2 } ->
476484 value = difference ( key , v1 , v2 )
@@ -479,15 +487,14 @@ defmodule Module.Types.Descr do
479487 % { } ->
480488 empty_key? ( key , v1 )
481489 end and
482- iterator_empty_difference_static ?( :maps . next ( iterator ) , map )
490+ iterator_empty_difference_subtype ?( :maps . next ( iterator ) , map )
483491 end
484492
485- defp iterator_empty_difference_static ?( :none , _map ) , do: true
493+ defp iterator_empty_difference_subtype ?( :none , _map ) , do: true
486494
487495 # Returning 0 from the callback is taken as none() for that subtype.
488496 defp difference ( :atom , v1 , v2 ) , do: atom_difference ( v1 , v2 )
489497 defp difference ( :bitmap , v1 , v2 ) , do: v1 - ( v1 &&& v2 )
490- defp difference ( :dynamic , v1 , v2 ) , do: dynamic_difference ( v1 , v2 )
491498 defp difference ( :list , v1 , v2 ) , do: list_difference ( v1 , v2 )
492499 defp difference ( :map , v1 , v2 ) , do: map_difference ( v1 , v2 )
493500 defp difference ( :optional , 1 , 1 ) , do: 0
@@ -535,7 +542,6 @@ defmodule Module.Types.Descr do
535542 defp empty_key? ( :map , value ) , do: map_empty? ( value )
536543 defp empty_key? ( :list , value ) , do: list_empty? ( value )
537544 defp empty_key? ( :tuple , value ) , do: tuple_empty? ( value )
538- defp empty_key? ( :dynamic , value ) , do: empty? ( value )
539545 defp empty_key? ( _ , _value ) , do: false
540546
541547 @ doc """
@@ -662,7 +668,7 @@ defmodule Module.Types.Descr do
662668 end
663669
664670 defp subtype_static? ( same , same ) , do: true
665- defp subtype_static? ( left , right ) , do: empty_difference_static ?( left , right )
671+ defp subtype_static? ( left , right ) , do: empty_difference_subtype ?( left , right )
666672
667673 @ doc """
668674 Check if a type is equal to another.
@@ -2116,13 +2122,6 @@ defmodule Module.Types.Descr do
21162122 defp dynamic_intersection ( left , right ) ,
21172123 do: symmetrical_intersection ( unfold ( left ) , unfold ( right ) , & intersection / 3 )
21182124
2119- defp dynamic_difference ( left , right ) do
2120- case difference_static ( left , right ) do
2121- value when value == @ none -> 0
2122- value -> value
2123- end
2124- end
2125-
21262125 defp dynamic_to_quoted ( descr , opts ) do
21272126 cond do
21282127 descr == % { } ->
0 commit comments