Skip to content

Commit d12d4c2

Browse files
committed
Closes #14598
1 parent a5b896a commit d12d4c2

File tree

3 files changed

+26
-37
lines changed

3 files changed

+26
-37
lines changed

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

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,7 @@ defmodule Module.Types.Descr do
11711171
with {:ok, domain, static_arrows, dynamic_arrows} <-
11721172
fun_normalize_both(fun_static, fun_dynamic, arity) do
11731173
cond do
1174-
empty?(args_domain) ->
1174+
Enum.any?(arguments, &empty?/1) ->
11751175
{:badarg, domain_to_flat_args(domain, arity)}
11761176

11771177
not subtype?(args_domain, domain) ->
@@ -1182,26 +1182,21 @@ defmodule Module.Types.Descr do
11821182
end
11831183

11841184
static? ->
1185-
{:ok, fun_apply_static(arguments, static_arrows, false)}
1185+
{:ok, fun_apply_static(arguments, static_arrows)}
11861186

11871187
static_arrows == [] ->
11881188
# TODO: We need to validate this within the theory
11891189
arguments = Enum.map(arguments, &upper_bound/1)
1190-
{:ok, dynamic(fun_apply_static(arguments, dynamic_arrows, false))}
1190+
{:ok, dynamic(fun_apply_static(arguments, dynamic_arrows))}
11911191

11921192
true ->
11931193
# For dynamic cases, combine static and dynamic results
1194-
{static_args, dynamic_args, maybe_empty?} =
1195-
if args_dynamic? do
1196-
{Enum.map(arguments, &upper_bound/1), Enum.map(arguments, &lower_bound/1), true}
1197-
else
1198-
{arguments, arguments, false}
1199-
end
1194+
arguments = Enum.map(arguments, &upper_bound/1)
12001195

12011196
{:ok,
12021197
union(
1203-
fun_apply_static(static_args, static_arrows, false),
1204-
dynamic(fun_apply_static(dynamic_args, dynamic_arrows, maybe_empty?))
1198+
fun_apply_static(arguments, static_arrows),
1199+
dynamic(fun_apply_static(arguments, dynamic_arrows))
12051200
)}
12061201
end
12071202
end
@@ -1301,26 +1296,12 @@ defmodule Module.Types.Descr do
13011296
:badfun
13021297
end
13031298

1304-
defp fun_apply_static(arguments, arrows, maybe_empty?) do
1299+
defp fun_apply_static(arguments, arrows) do
13051300
type_args = args_to_domain(arguments)
13061301

1307-
# Optimization: short-circuits when inner loop is none() or outer loop is term()
1308-
if maybe_empty? and empty?(type_args) do
1309-
Enum.reduce_while(arrows, none(), fn intersection_of_arrows, acc ->
1310-
Enum.reduce_while(intersection_of_arrows, term(), fn
1311-
{_dom, _ret}, acc when acc == @none -> {:halt, acc}
1312-
{_dom, ret}, acc -> {:cont, intersection(acc, ret)}
1313-
end)
1314-
|> case do
1315-
:term -> {:halt, :term}
1316-
inner -> {:cont, union(inner, acc)}
1317-
end
1318-
end)
1319-
else
1320-
Enum.reduce(arrows, none(), fn intersection_of_arrows, acc ->
1321-
aux_apply(acc, type_args, term(), intersection_of_arrows)
1322-
end)
1323-
end
1302+
Enum.reduce(arrows, none(), fn intersection_of_arrows, acc ->
1303+
aux_apply(acc, type_args, term(), intersection_of_arrows)
1304+
end)
13241305
end
13251306

13261307
# Helper function for function application that handles the application of
@@ -1483,7 +1464,7 @@ defmodule Module.Types.Descr do
14831464
# This avoids the expensive recursive phi computation by checking only that applying the
14841465
# input to the positive intersection yields a subtype of the return
14851466
if all_non_empty_domains?([{arguments, return} | positives]) do
1486-
fun_apply_static(arguments, [positives], false)
1467+
fun_apply_static(arguments, [positives])
14871468
|> subtype?(return)
14881469
else
14891470
n = length(arguments)

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -919,16 +919,14 @@ defmodule Module.Types.DescrTest do
919919
assert fun_apply(fun([dynamic()], term()), [dynamic()]) == {:ok, term()}
920920
assert fun_apply(fun([integer()], dynamic()), [integer()]) == {:ok, dynamic()}
921921

922-
assert fun_apply(fun([dynamic()], integer()), [dynamic()])
923-
|> elem(1)
924-
|> equal?(integer())
922+
assert fun_apply(fun([dynamic()], integer()), [dynamic()]) ==
923+
{:ok, union(integer(), dynamic())}
925924

926-
assert fun_apply(fun([dynamic(), atom()], float()), [dynamic(), atom()])
927-
|> elem(1)
928-
|> equal?(float())
925+
assert fun_apply(fun([dynamic(), atom()], float()), [dynamic(), atom()]) ==
926+
{:ok, union(float(), dynamic())}
929927

930928
fun = fun([dynamic(integer())], atom())
931-
assert fun_apply(fun, [dynamic(integer())]) |> elem(1) |> equal?(atom())
929+
assert fun_apply(fun, [dynamic(integer())]) == {:ok, union(atom(), dynamic())}
932930
assert fun_apply(fun, [dynamic(number())]) == {:ok, dynamic()}
933931
assert fun_apply(fun, [integer()]) == {:ok, dynamic()}
934932
assert fun_apply(fun, [float()]) == {:badarg, [dynamic(integer())]}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ defmodule Module.Types.ExprTest do
169169
data -> data
170170
end).(map)
171171
) == dynamic()
172+
173+
assert typecheck!(
174+
[],
175+
[true, false]
176+
|> Enum.random()
177+
|> then(fn
178+
true -> :ok
179+
_ -> :error
180+
end)
181+
) == dynamic(atom([:ok, :error]))
172182
end
173183

174184
test "bad function" do

0 commit comments

Comments
 (0)