@@ -2759,7 +2759,7 @@ defmodule Module.Types.Descr do
27592759 acc
27602760
27612761 :bdd_top ->
2762- if map_empty ?( tag , fields , negs ) , do: acc , else: [ { tag , fields , negs } | acc ]
2762+ if map_line_empty ?( tag , fields , negs ) , do: acc , else: [ { tag , fields , negs } | acc ]
27632763
27642764 { { next_tag , next_fields } = next_map , left , right } ->
27652765 acc =
@@ -3407,13 +3407,31 @@ defmodule Module.Types.Descr do
34073407 # Short-circuits if it finds a non-empty map literal in the union.
34083408 # Since the algorithm is recursive, we implement the short-circuiting
34093409 # as throw/catch.
3410- defp map_empty? ( bdd ) , do: map_bdd_get ( bdd ) == [ ]
3410+ defp map_empty? ( bdd ) , do: map_bdd_empty? ( { :open , % { } } , [ ] , bdd )
34113411
3412- defp map_empty? ( _ , pos , [ ] ) , do: Enum . any? ( Map . to_list ( pos ) , fn { _ , v } -> empty? ( v ) end )
3413- defp map_empty? ( _ , _ , [ { :open , neg_fields } | _ ] ) when neg_fields == % { } , do: true
3414- defp map_empty? ( :open , fs , [ { :closed , _ } | negs ] ) , do: map_empty? ( :open , fs , negs )
3412+ defp map_bdd_empty? ( { tag , fields } = map , negs , bdd ) do
3413+ case bdd do
3414+ :bdd_bot ->
3415+ true
3416+
3417+ :bdd_top ->
3418+ map_line_empty? ( tag , fields , negs )
3419+
3420+ { { next_tag , next_fields } = next_map , left , right } ->
3421+ try do
3422+ new_map = map_literal_intersection ( tag , fields , next_tag , next_fields )
3423+ map_bdd_empty? ( new_map , negs , left ) and map_bdd_empty? ( map , [ next_map | negs ] , right )
3424+ catch
3425+ :empty -> map_bdd_empty? ( map , [ next_map | negs ] , right )
3426+ end
3427+ end
3428+ end
3429+
3430+ defp map_line_empty? ( _ , pos , [ ] ) , do: Enum . any? ( Map . to_list ( pos ) , fn { _ , v } -> empty? ( v ) end )
3431+ defp map_line_empty? ( _ , _ , [ { :open , neg_fields } | _ ] ) when neg_fields == % { } , do: true
3432+ defp map_line_empty? ( :open , fs , [ { :closed , _ } | negs ] ) , do: map_line_empty? ( :open , fs , negs )
34153433
3416- defp map_empty ?( tag , fields , [ { neg_tag , neg_fields } | negs ] ) do
3434+ defp map_line_empty ?( tag , fields , [ { neg_tag , neg_fields } | negs ] ) do
34173435 if map_check_domain_keys ( tag , neg_tag ) do
34183436 atom_default = map_key_tag_to_type ( tag )
34193437 neg_atom_default = map_key_tag_to_type ( neg_tag )
@@ -3432,18 +3450,18 @@ defmodule Module.Types.Descr do
34323450 # There may be value in common
34333451 tag == :open ->
34343452 diff = difference ( term_or_optional ( ) , neg_type )
3435- empty? ( diff ) or map_empty ?( tag , Map . put ( fields , neg_key , diff ) , negs )
3453+ empty? ( diff ) or map_line_empty ?( tag , Map . put ( fields , neg_key , diff ) , negs )
34363454
34373455 true ->
34383456 diff = difference ( atom_default , neg_type )
3439- empty? ( diff ) or map_empty ?( tag , Map . put ( fields , neg_key , diff ) , negs )
3457+ empty? ( diff ) or map_line_empty ?( tag , Map . put ( fields , neg_key , diff ) , negs )
34403458 end
34413459 end ) and
34423460 Enum . all? ( Map . to_list ( fields ) , fn { key , type } ->
34433461 case neg_fields do
34443462 % { ^ key => neg_type } ->
34453463 diff = difference ( type , neg_type )
3446- empty? ( diff ) or map_empty ?( tag , Map . put ( fields , key , diff ) , negs )
3464+ empty? ( diff ) or map_line_empty ?( tag , Map . put ( fields , key , diff ) , negs )
34473465
34483466 % { } ->
34493467 cond do
@@ -3456,12 +3474,12 @@ defmodule Module.Types.Descr do
34563474 true ->
34573475 # an absent key in a open negative map can be ignored
34583476 diff = difference ( type , neg_atom_default )
3459- empty? ( diff ) or map_empty ?( tag , Map . put ( fields , key , diff ) , negs )
3477+ empty? ( diff ) or map_line_empty ?( tag , Map . put ( fields , key , diff ) , negs )
34603478 end
34613479 end
3462- end ) ) or map_empty ?( tag , fields , negs )
3480+ end ) ) or map_line_empty ?( tag , fields , negs )
34633481 else
3464- map_empty ?( tag , fields , negs )
3482+ map_line_empty ?( tag , fields , negs )
34653483 end
34663484 end
34673485
0 commit comments