Skip to content

Commit 4922f30

Browse files
authored
Deduplicate tuple DNF entries (#15267)
1 parent a1e668b commit 4922f30

2 files changed

Lines changed: 13 additions & 0 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5278,6 +5278,9 @@ defmodule Module.Types.Descr do
52785278
{tag, elements} -> tuple_eliminate_negations(tag, elements, negs)
52795279
end
52805280
end)
5281+
# We want to avoid each_singleton? from failing,
5282+
# so we remove contiguous duplicates (cheaper than uniq)
5283+
|> Enum.dedup()
52815284
end
52825285

52835286
defp tuple_bdd_to_dnf_with_negations(bdd) do

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,16 @@ defmodule Module.Types.DescrTest do
14221422
refute singleton?(open_tuple([]))
14231423
refute singleton?(union(tuple([atom([:value])]), tuple([atom([:other_value])])))
14241424
refute singleton?(union(tuple([atom([:value])]), closed_map(other: atom([:value]))))
1425+
1426+
# Both BDD lines produce the same singleton tuple, so the tuple DNF must not duplicate it.
1427+
a = tuple([union(integer(), atom([:ok])), atom([:x])])
1428+
b = tuple([integer(), atom([:x, :y])])
1429+
c = tuple([integer(), union(atom([:x]), binary())])
1430+
1431+
t = union(difference(a, b), difference(a, c))
1432+
# Semantically t ~= {:ok, :x}, confirmed by equal?
1433+
assert equal?(t, tuple([atom([:ok]), atom([:x])]))
1434+
assert singleton?(t)
14251435
end
14261436
end
14271437

0 commit comments

Comments
 (0)