Skip to content

Commit 20daffb

Browse files
gldubcjosevalim
authored andcommitted
Remove duplicate for map_difference
1 parent a4f40f7 commit 20daffb

File tree

1 file changed

+34
-24
lines changed

1 file changed

+34
-24
lines changed

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

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,16 +2443,7 @@ defmodule Module.Types.Descr do
24432443
acc ->
24442444
try do
24452445
{tag, fields} = map_literal_intersection(tag1, pos1, tag2, pos2)
2446-
entry = {tag, fields, negs1 ++ negs2}
2447-
2448-
# Imagine a, b, c, where a is closed and b and c are open with
2449-
# no keys in common. The result in both cases will be a and we
2450-
# want to avoid adding duplicates, especially as intersection
2451-
# is a cartesian product.
2452-
case :lists.member(entry, acc) do
2453-
true -> acc
2454-
false -> [entry | acc]
2455-
end
2446+
prepend_to_map_dnf(tag, fields, negs1 ++ (negs2 -- negs1), acc)
24562447
catch
24572448
:empty -> acc
24582449
end
@@ -2567,42 +2558,61 @@ defmodule Module.Types.Descr do
25672558
if empty?(type), do: throw(:empty), else: type
25682559
end
25692560

2570-
defp map_difference(_, dnf) when dnf == @map_top do
2571-
0
2572-
end
2561+
defp map_difference(_, dnf) when dnf == @map_top, do: []
2562+
defp map_difference(dnf, dnf), do: []
25732563

25742564
defp map_difference(dnf1, dnf2) do
25752565
Enum.reduce(dnf2, dnf1, fn
2576-
# Optimization: we are removing an open map with one field.
2577-
{:open, fields2, []}, dnf1 when map_size(fields2) == 1 ->
2578-
Enum.reduce(dnf1, [], fn {tag1, fields1, negs1}, acc ->
2566+
{:open, fields2, []}, current_dnf when map_size(fields2) == 1 ->
2567+
# Optimization: we are removing an open map with one field.
2568+
Enum.reduce(current_dnf, [], fn {tag1, fields1, negs1}, acc ->
25792569
{key, value, _rest} = :maps.next(:maps.iterator(fields2))
25802570
t_diff = difference(Map.get(fields1, key, map_key_tag_to_type(tag1)), value)
25812571

25822572
if empty?(t_diff) do
25832573
acc
25842574
else
2585-
[{tag1, Map.put(fields1, key, t_diff), negs1} | acc]
2575+
{tag, pos} = {tag1, Map.put(fields1, key, t_diff)}
2576+
entry = {tag, pos, negs1}
2577+
2578+
cond do
2579+
:lists.member({tag, pos}, negs1) -> acc
2580+
:lists.member(entry, acc) -> acc
2581+
true -> [entry | acc]
2582+
end
25862583
end
25872584
end)
25882585

2589-
{tag2, fields2, negs2}, dnf1 ->
2590-
Enum.reduce(dnf1, [], fn {tag1, fields1, negs1}, acc ->
2591-
acc = [{tag1, fields1, [{tag2, fields2} | negs1]} | acc]
2586+
{tag2, fields2, negs2}, current_dnf ->
2587+
Enum.reduce(current_dnf, [], fn {tag1, fields1, negs1}, acc ->
2588+
negs =
2589+
if :lists.member({tag2, fields2}, negs1) do
2590+
negs1
2591+
else
2592+
[{tag2, fields2} | negs1]
2593+
end
2594+
2595+
acc = prepend_to_map_dnf(tag1, fields1, negs, acc)
25922596

25932597
Enum.reduce(negs2, acc, fn {neg_tag2, neg_fields2}, acc ->
25942598
try do
25952599
{tag, fields} = map_literal_intersection(tag1, fields1, neg_tag2, neg_fields2)
2596-
[{tag, fields, negs1} | acc]
2600+
prepend_to_map_dnf(tag, fields, negs1, acc)
25972601
catch
25982602
:empty -> acc
25992603
end
26002604
end)
26012605
end)
26022606
end)
2603-
|> case do
2604-
[] -> 0
2605-
acc -> acc
2607+
end
2608+
2609+
defp prepend_to_map_dnf(tag, fields, negs, acc) do
2610+
entry = {tag, fields, negs}
2611+
2612+
cond do
2613+
:lists.member({tag, fields}, negs) -> acc
2614+
:lists.member(entry, acc) -> acc
2615+
true -> [entry | acc]
26062616
end
26072617
end
26082618

0 commit comments

Comments
 (0)