@@ -3080,29 +3080,30 @@ defmodule Module.Types.Descr do
30803080 defp map_difference ( _ , bdd_leaf ( :open , [ ] ) ) ,
30813081 do: :bdd_bot
30823082
3083- defp map_difference ( bdd_leaf ( tag , fields ) = map1 , bdd_leaf ( :open , [ { key , v2 } ] ) ) do
3083+ defp map_difference ( bdd1 , bdd2 ) ,
3084+ do: bdd_difference ( bdd1 , bdd2 , & map_leaf_difference / 3 )
3085+
3086+ # We only apply this particular optimization when comparing leafs (type == :none).
3087+ # Applying it in other scenarios lead to slow compilation, likely because the
3088+ # introduction of `a_int` and `a_union` lead to additional nodes and large rehashes
3089+ # of the tree.
3090+ #
3091+ # Outside of this particular scenario, the `a_int` optimization has been useful,
3092+ # but we haven't measured benefits for `a_union`.
3093+ defp map_leaf_difference ( bdd_leaf ( tag , fields ) , bdd_leaf ( :open , [ { key , v2 } ] ) , :none ) do
30843094 { found? , v1 } =
30853095 case fields_find ( key , fields ) do
30863096 { :ok , value } -> { true , value }
30873097 :error -> { false , map_key_tag_to_type ( tag ) }
30883098 end
30893099
30903100 if tag == :closed and not found? and not is_optional_static ( v2 ) do
3091- map1
3101+ :disjoint
30923102 else
3093- v_diff = difference ( v1 , v2 )
3094-
3095- if empty? ( v_diff ) do
3096- :bdd_bot
3097- else
3098- bdd_leaf ( tag , fields_store ( key , v_diff , fields ) )
3099- end
3103+ map_leaf_one_key_difference ( tag , fields , key , v1 , v2 , :none )
31003104 end
31013105 end
31023106
3103- defp map_difference ( bdd1 , bdd2 ) ,
3104- do: bdd_difference ( bdd1 , bdd2 , & map_leaf_difference / 3 )
3105-
31063107 defp map_leaf_difference ( bdd_leaf ( tag , fields ) , bdd_leaf ( neg_tag , neg_fields ) , type ) do
31073108 case map_difference_strategy ( fields , neg_fields , tag , neg_tag ) do
31083109 :disjoint ->
@@ -5884,17 +5885,6 @@ defmodule Module.Types.Descr do
58845885
58855886 ## Optimize differences
58865887
5887- defp bdd_difference ( bdd_leaf ( _ , _ ) = bdd1 , bdd_leaf ( _ , _ ) = bdd2 , leaf_compare ) do
5888- case leaf_compare . ( bdd1 , bdd2 , :none ) do
5889- :disjoint -> bdd1
5890- { :one_key_difference , a_diff , _a_none } -> a_diff
5891- :subtype -> :bdd_bot
5892- :none when bdd2 < bdd1 -> { bdd2 , :bdd_bot , :bdd_bot , bdd1 }
5893- :none when bdd1 < bdd2 -> { bdd1 , bdd_negation ( bdd2 ) , :bdd_bot , :bdd_bot }
5894- :none -> :bdd_bot
5895- end
5896- end
5897-
58985888 # For the right-side being a leaf, we have:
58995889 #
59005890 # ((a1 and C1) or U1 or (not a1 and D1)) and not a2
@@ -5933,21 +5923,8 @@ defmodule Module.Types.Descr do
59335923 :subtype ->
59345924 bdd_union ( bdd_difference ( u1 , bdd2 , leaf_compare ) , bdd_difference ( d1 , bdd2 , leaf_compare ) )
59355925
5936- :none when a1 < bdd2 ->
5937- { a1 , bdd_difference ( c1 , bdd2 , leaf_compare ) , bdd_difference ( u1 , bdd2 , leaf_compare ) ,
5938- bdd_difference ( d1 , bdd2 , leaf_compare ) }
5939-
5940- :none when bdd2 < a1 ->
5941- { bdd2 , :bdd_bot , :bdd_bot , bdd1 }
5942-
59435926 :none ->
5944- # There is no point in traversing down if they are equal,
5945- # as we can assume this check already happened when building bdd1
5946- { bdd2 , :bdd_bot , :bdd_bot , bdd_union ( u1 , d1 ) }
5947- end
5948- |> case do
5949- { _ , :bdd_bot , u , :bdd_bot } -> u
5950- other -> other
5927+ bdd_difference ( bdd1 , bdd2 )
59515928 end
59525929 end
59535930
@@ -5993,8 +5970,9 @@ defmodule Module.Types.Descr do
59935970 #
59945971 defp bdd_difference ( bdd_leaf ( _ , _ ) = bdd1 , bdd2 , leaf_compare ) when is_tuple ( bdd2 ) do
59955972 { a2 , c2 , u2 , d2 } = bdd_expand ( bdd2 )
5973+ type = if c2 == :bdd_top , do: :none , else: :intersection
59965974
5997- case leaf_compare . ( bdd1 , a2 , :intersection ) do
5975+ case leaf_compare . ( bdd1 , a2 , type ) do
59985976 :disjoint ->
59995977 bdd1 |> bdd_difference ( d2 , leaf_compare ) |> bdd_difference ( u2 , leaf_compare )
60005978
@@ -6007,21 +5985,8 @@ defmodule Module.Types.Descr do
60075985 :subtype ->
60085986 bdd1 |> bdd_difference ( c2 , leaf_compare ) |> bdd_difference ( u2 , leaf_compare )
60095987
6010- :none when a2 < bdd1 ->
6011- { a2 , bdd_difference ( bdd1 , bdd_union ( c2 , u2 ) , leaf_compare ) , :bdd_bot ,
6012- bdd_difference ( bdd1 , bdd_union ( d2 , u2 ) , leaf_compare ) }
6013-
6014- :none when bdd1 < a2 ->
6015- { bdd1 , bdd_negation ( bdd2 ) , :bdd_bot , :bdd_bot }
6016-
60175988 :none ->
6018- # There is no point in traversing down if they are equal,
6019- # as we can assume this check already happened when building bdd2
6020- { bdd1 , bdd_negation ( bdd_union ( c2 , u2 ) ) , :bdd_bot , :bdd_bot }
6021- end
6022- |> case do
6023- { _ , :bdd_bot , u , :bdd_bot } -> u
6024- other -> other
5989+ bdd_difference ( bdd1 , bdd2 )
60255990 end
60265991 end
60275992
0 commit comments