Skip to content

Commit ae48087

Browse files
committed
Format and memoize without process cache
1 parent f01c078 commit ae48087

File tree

2 files changed

+24
-22
lines changed

2 files changed

+24
-22
lines changed

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

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,61 +1478,62 @@ defmodule Module.Types.Descr do
14781478
false
14791479
else
14801480
# Initialize memoization cache for the recursive phi computation
1481-
Process.put(:phi_cache, %{})
14821481
arguments = Enum.map(arguments, &{false, &1})
1483-
phi(arguments, {false, negation(return)}, positives)
1482+
{result, _cache} = phi(arguments, {false, negation(return)}, positives, %{})
1483+
result
14841484
end
14851485
end
14861486
end
14871487

1488-
defp all_non_empty_domains?(positives) do
1489-
Enum.all?(positives, fn {args, _ret} -> not empty?(args_to_domain(args)) end)
1490-
end
1491-
1492-
defp phi(args, {b, t}, []) do
1493-
Enum.any?(args, fn {bool, typ} -> bool and empty?(typ) end) or (b and empty?(t))
1488+
defp phi(args, {b, t}, [], cache) do
1489+
{Enum.any?(args, fn {bool, typ} -> bool and empty?(typ) end) or (b and empty?(t)), cache}
14941490
end
14951491

1496-
defp phi(args, {b, ret}, [{arguments, return} | rest_positive]) do
1492+
defp phi(args, {b, ret}, [{arguments, return} | rest_positive], cache) do
14971493
# Create cache key from function arguments
14981494
cache_key = {args, {b, ret}, [{arguments, return} | rest_positive]}
1499-
cache = Process.get(:phi_cache, %{})
15001495

15011496
case Map.get(cache, cache_key) do
15021497
nil ->
15031498
# Compute result and cache it
1504-
result1 = phi(args, {true, intersection(ret, return)}, rest_positive)
1499+
{result1, cache} = phi(args, {true, intersection(ret, return)}, rest_positive, cache)
15051500

15061501
if not result1 do
1507-
Process.put(:phi_cache, Map.put(cache, cache_key, false))
1508-
false
1502+
# Store false result in cache
1503+
cache = Map.put(cache, cache_key, false)
1504+
{false, cache}
15091505
else
15101506
# This doesn't stop if one intermediate result is false?
1511-
result2 =
1507+
{result2, cache} =
15121508
Enum.with_index(arguments)
1513-
|> Enum.reduce_while(true, fn {type, index}, acc_result ->
1514-
new_result =
1509+
|> Enum.reduce_while({true, cache}, fn {type, index}, {acc_result, acc_cache} ->
1510+
{new_result, new_cache} =
15151511
List.update_at(args, index, fn {_, arg} -> {true, difference(arg, type)} end)
1516-
|> phi({b, ret}, rest_positive)
1512+
|> phi({b, ret}, rest_positive, acc_cache)
15171513

15181514
if new_result do
1519-
{:cont, acc_result and new_result}
1515+
{:cont, {acc_result and new_result, new_cache}}
15201516
else
1521-
{:halt, false}
1517+
{:halt, {false, new_cache}}
15221518
end
15231519
end)
15241520

15251521
result = result1 and result2
1526-
Process.put(:phi_cache, Map.put(cache, cache_key, result))
1527-
result
1522+
# Store result in cache
1523+
cache = Map.put(cache, cache_key, result)
1524+
{result, cache}
15281525
end
15291526

15301527
cached_result ->
15311528
# Return cached result
1532-
cached_result
1529+
{cached_result, cache}
15331530
end
15341531
end
15351532

1533+
defp all_non_empty_domains?(positives) do
1534+
Enum.all?(positives, fn {args, _ret} -> not empty?(args_to_domain(args)) end)
1535+
end
1536+
15361537
defp fun_union(bdd1, bdd2) do
15371538
case {bdd1, bdd2} do
15381539
{:fun_top, _} -> :fun_top

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ defmodule Module.Types.DescrTest do
674674
assert subtype?(f, fun([none(), integer()], term()))
675675
assert subtype?(fun([none(), number()], atom()), f)
676676
assert subtype?(fun([tuple(), number()], atom()), f)
677+
677678
# (none, float)->atom is not a subtype of (none, integer)->atom because float has an empty intersection with integer
678679
# it's only possible to find this out by doing the
679680
# intersection one by one.

0 commit comments

Comments
 (0)