Skip to content

Commit bafb68d

Browse files
committed
Another attempt to work around Erlang/OTP compiler bug
1 parent 24ebb96 commit bafb68d

1 file changed

Lines changed: 66 additions & 77 deletions

File tree

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

Lines changed: 66 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5878,6 +5878,23 @@ defmodule Module.Types.Descr do
58785878

58795879
## Optimize differences
58805880

5881+
defp bdd_difference(bdd_leaf(_, _) = a1, bdd_leaf(_, _) = a2, leaf_compare) do
5882+
case leaf_compare.(a1, a2, :none) do
5883+
:disjoint -> a1
5884+
:subtype -> :bdd_bot
5885+
{:one_key_difference, a_diff, _} -> a_diff
5886+
:none -> bdd_difference(a1, a2)
5887+
end
5888+
end
5889+
5890+
defp bdd_difference(bdd1, bdd2, leaf_compare) when is_tuple(bdd1) and is_tuple(bdd2) do
5891+
bdd_difference(bdd_expand(bdd1), bdd_expand(bdd2), bdd1, bdd2, leaf_compare)
5892+
end
5893+
5894+
defp bdd_difference(bdd1, bdd2, _leaf_compare) do
5895+
bdd_difference(bdd1, bdd2)
5896+
end
5897+
58815898
# We have two formulas for differences.
58825899
#
58835900
# ## When D1 = bottom
@@ -5906,93 +5923,65 @@ defmodule Module.Types.Descr do
59065923
#
59075924
# ((U1 and not a2) or (D1 and not D2)) and not U2 and not D2
59085925
#
5909-
defp bdd_difference(bdd_leaf(_, _) = a1, bdd_leaf(_, _) = a2, leaf_compare) do
5910-
case leaf_compare.(a1, a2, :none) do
5911-
:disjoint -> a1
5912-
:subtype -> :bdd_bot
5913-
{:one_key_difference, a_diff, _} -> a_diff
5914-
:none -> bdd_difference(a1, a2)
5915-
end
5916-
end
5926+
defp bdd_difference({a1, :bdd_top, u1, :bdd_bot}, {a2, c2, u2, d2}, bdd1, bdd2, leaf_compare) do
5927+
type = if c2 == :bdd_top, do: :none, else: :intersection
59175928

5918-
defp bdd_difference(bdd1, bdd2, leaf_compare) when is_tuple(bdd1) and is_tuple(bdd2) do
5919-
# TODO: Use bdd_expand on Erlang/OTP 28.
5920-
# We write the case by hand to address a bug in Erlang/OTP 27.0
5921-
{a1, c1, u1, d1} =
5922-
case bdd1 do
5923-
bdd_leaf(_, _) -> {bdd1, :bdd_top, :bdd_bot, :bdd_bot}
5924-
_ -> bdd1
5925-
end
5926-
5927-
{a2, c2, u2, d2} =
5928-
case bdd2 do
5929-
bdd_leaf(_, _) -> {bdd2, :bdd_top, :bdd_bot, :bdd_bot}
5930-
_ -> bdd2
5931-
end
5932-
5933-
cond do
5934-
d1 == :bdd_bot and c1 == :bdd_top ->
5935-
type = if c2 == :bdd_top, do: :none, else: :intersection
5936-
5937-
case leaf_compare.(a1, a2, type) do
5938-
:disjoint ->
5939-
a1
5940-
|> bdd_difference(d2, leaf_compare)
5941-
|> bdd_difference(u2, leaf_compare)
5942-
|> bdd_union(bdd_difference(u1, bdd2, leaf_compare))
5943-
5944-
:subtype ->
5945-
a1
5946-
|> bdd_difference(c2, leaf_compare)
5947-
|> bdd_difference(u2, leaf_compare)
5948-
|> bdd_union(bdd_difference(u1, bdd2, leaf_compare))
5949-
5950-
{:one_key_difference, a_diff, a_int} ->
5951-
bdd_union(
5952-
a_diff |> bdd_difference(d2, leaf_compare) |> bdd_difference(u2, leaf_compare),
5953-
a_int |> bdd_difference(c2, leaf_compare) |> bdd_difference(u2, leaf_compare)
5954-
)
5955-
|> bdd_union(bdd_difference(u1, bdd2, leaf_compare))
5956-
5957-
:none ->
5958-
bdd_difference(bdd1, bdd2)
5959-
end
5929+
case leaf_compare.(a1, a2, type) do
5930+
:disjoint ->
5931+
a1
5932+
|> bdd_difference(d2, leaf_compare)
5933+
|> bdd_difference(u2, leaf_compare)
5934+
|> bdd_union(bdd_difference(u1, bdd2, leaf_compare))
5935+
5936+
:subtype ->
5937+
a1
5938+
|> bdd_difference(c2, leaf_compare)
5939+
|> bdd_difference(u2, leaf_compare)
5940+
|> bdd_union(bdd_difference(u1, bdd2, leaf_compare))
5941+
5942+
{:one_key_difference, a_diff, a_int} ->
5943+
bdd_union(
5944+
a_diff |> bdd_difference(d2, leaf_compare) |> bdd_difference(u2, leaf_compare),
5945+
a_int |> bdd_difference(c2, leaf_compare) |> bdd_difference(u2, leaf_compare)
5946+
)
5947+
|> bdd_union(bdd_difference(u1, bdd2, leaf_compare))
59605948

5961-
c2 == :bdd_top ->
5962-
type = if d1 == :bdd_bot, do: :none, else: :union
5949+
:none ->
5950+
bdd_difference(bdd1, bdd2)
5951+
end
5952+
end
59635953

5964-
case leaf_compare.(a1, a2, type) do
5965-
:disjoint ->
5966-
bdd_difference(u1, a2, leaf_compare)
5967-
|> bdd_union(bdd_difference({a1, c1, :bdd_bot, d1}, a2))
5968-
|> bdd_difference(d2, leaf_compare)
5969-
|> bdd_difference(u2, leaf_compare)
5970-
5971-
:subtype ->
5972-
bdd_union(
5973-
bdd_difference(u1, a2, leaf_compare),
5974-
bdd_difference(d1, a2, leaf_compare)
5975-
)
5976-
|> bdd_difference(d2, leaf_compare)
5977-
|> bdd_difference(u2, leaf_compare)
5954+
defp bdd_difference({a1, c1, u1, d1}, {a2, :bdd_top, u2, d2}, bdd1, bdd2, leaf_compare) do
5955+
type = if d1 == :bdd_bot, do: :none, else: :union
59785956

5979-
{:one_key_difference, a_diff, a_union} ->
5980-
bdd_intersection(a_diff, c1)
5981-
|> bdd_union(bdd_difference(u1, a2, leaf_compare))
5982-
|> bdd_union(bdd_difference(d1, a_union, leaf_compare))
5983-
|> bdd_difference(d2, leaf_compare)
5984-
|> bdd_difference(u2, leaf_compare)
5957+
case leaf_compare.(a1, a2, type) do
5958+
:disjoint ->
5959+
bdd_difference(u1, a2, leaf_compare)
5960+
|> bdd_union(bdd_difference({a1, c1, :bdd_bot, d1}, a2))
5961+
|> bdd_difference(d2, leaf_compare)
5962+
|> bdd_difference(u2, leaf_compare)
5963+
5964+
:subtype ->
5965+
bdd_union(
5966+
bdd_difference(u1, a2, leaf_compare),
5967+
bdd_difference(d1, a2, leaf_compare)
5968+
)
5969+
|> bdd_difference(d2, leaf_compare)
5970+
|> bdd_difference(u2, leaf_compare)
59855971

5986-
:none ->
5987-
bdd_difference(bdd1, bdd2)
5988-
end
5972+
{:one_key_difference, a_diff, a_union} ->
5973+
bdd_intersection(a_diff, c1)
5974+
|> bdd_union(bdd_difference(u1, a2, leaf_compare))
5975+
|> bdd_union(bdd_difference(d1, a_union, leaf_compare))
5976+
|> bdd_difference(d2, leaf_compare)
5977+
|> bdd_difference(u2, leaf_compare)
59895978

5990-
true ->
5979+
:none ->
59915980
bdd_difference(bdd1, bdd2)
59925981
end
59935982
end
59945983

5995-
defp bdd_difference(bdd1, bdd2, _leaf_compare) do
5984+
defp bdd_difference(_, _, bdd1, bdd2, _leaf_compare) do
59965985
bdd_difference(bdd1, bdd2)
59975986
end
59985987

0 commit comments

Comments
 (0)