Skip to content

Commit 426a429

Browse files
committed
Fix wrong bdd leaf intersection optimization on equal literals, closes #15091
1 parent be34850 commit 426a429

2 files changed

Lines changed: 17 additions & 7 deletions

File tree

lib/elixir/lib/module/types/descr.ex

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5218,7 +5218,7 @@ defmodule Module.Types.Descr do
52185218

52195219
case leaf_disjoint.(bdd1, leaf) do
52205220
true when u == :bdd_bot -> bdd1
5221-
true -> {bdd1, bdd_negation(u), :bdd_bot, :bdd_bot}
5221+
true -> bdd_difference(bdd1, u, leaf_disjoint)
52225222
false -> bdd_difference(bdd1, bdd2)
52235223
end
52245224
end
@@ -5376,8 +5376,11 @@ defmodule Module.Types.Descr do
53765376
bdd_leaf(_, _) ->
53775377
intersection.(leaf, bdd)
53785378

5379-
{lit, _, _, _} when lit == leaf ->
5380-
bdd
5379+
{lit, c, u, _} when lit == leaf ->
5380+
case bdd_union(c, u) do
5381+
:bdd_bot -> :bdd_bot
5382+
cu -> {lit, cu, :bdd_bot, :bdd_bot}
5383+
end
53815384

53825385
{lit, c, u, d} ->
53835386
rest =

lib/elixir/test/elixir/module/types/descr_test.exs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ defmodule Module.Types.DescrTest do
303303

304304
assert empty?(intersection(closed_map(a: integer()), closed_map(a: atom())))
305305

306-
# Maps leaves are actually optimize, so some of the code branches
306+
# Maps leaves are actually optimized, so some of the code branches
307307
# can only be tested through negations. This is the intersection between
308308
# open_map(a: integer()) and open_map(b: integer())
309309
a_and_b =
@@ -317,6 +317,16 @@ defmodule Module.Types.DescrTest do
317317
),
318318
a_and_b
319319
)
320+
321+
# This is a regression triggered by an optimization
322+
assert intersection(
323+
closed_map(tag: atom([true]), halted: atom([true]), assigns: term()),
324+
union(
325+
closed_map(tag: atom([true]), halted: atom([true]), assigns: term()),
326+
closed_map(tag: atom([true]), halted: term(), assigns: open_map())
327+
)
328+
)
329+
|> equal?(closed_map(tag: atom([true]), halted: atom([true]), assigns: term()))
320330
end
321331

322332
test "map with domain keys" do
@@ -367,13 +377,10 @@ defmodule Module.Types.DescrTest do
367377

368378
t1 = closed_map([{domain_key(:integer), atom()}])
369379
t2 = closed_map([{domain_key(:integer), binary()}])
370-
371380
assert equal?(intersection(t1, t2), empty_map())
372381

373382
t1 = closed_map([{domain_key(:integer), atom()}])
374383
t2 = closed_map([{domain_key(:atom), term()}])
375-
376-
# their intersection is the empty map
377384
refute empty?(intersection(t1, t2))
378385
assert equal?(intersection(t1, t2), empty_map())
379386
end

0 commit comments

Comments
 (0)