Skip to content

Commit 6710334

Browse files
committed
Inference of lists
1 parent c758109 commit 6710334

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

lib/elixir/lib/module/types/expr.ex

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,35 @@ defmodule Module.Types.Expr do
7676
do: {empty_list(), context}
7777

7878
# [expr, ...]
79-
# PENDING: here
80-
def of_expr(list, _expected, expr, stack, context) when is_list(list) do
79+
def of_expr(list, expected, expr, stack, context) when is_list(list) do
8180
{prefix, suffix} = unpack_list(list, [])
82-
{prefix, context} = Enum.map_reduce(prefix, context, &of_expr(&1, @pending, expr, stack, &2))
83-
{suffix, context} = of_expr(suffix, @pending, expr, stack, context)
8481

8582
if stack.mode == :traversal do
83+
{_, context} = Enum.map_reduce(prefix, context, &of_expr(&1, term(), expr, stack, &2))
84+
{_, context} = of_expr(suffix, term(), expr, stack, context)
8685
{dynamic(), context}
8786
else
87+
hd_type =
88+
case list_hd(expected) do
89+
{_, type} -> type
90+
_ -> term()
91+
end
92+
93+
{prefix, context} = Enum.map_reduce(prefix, context, &of_expr(&1, hd_type, expr, stack, &2))
94+
95+
{suffix, context} =
96+
if suffix == [] do
97+
{empty_list(), context}
98+
else
99+
tl_type =
100+
case list_tl(expected) do
101+
{_, type} -> type
102+
_ -> term()
103+
end
104+
105+
of_expr(suffix, tl_type, expr, stack, context)
106+
end
107+
88108
{non_empty_list(Enum.reduce(prefix, &union/2), suffix), context}
89109
end
90110
end

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ defmodule Module.Types.ExprTest do
4141
assert typecheck!([x], [:ok | x]) == dynamic(non_empty_list(term(), term()))
4242
end
4343

44+
test "inference" do
45+
assert typecheck!(
46+
[x, y, z],
47+
(
48+
List.to_integer([x, y | z])
49+
{x, y, z}
50+
)
51+
) == dynamic(tuple([integer(), integer(), list(integer())]))
52+
end
53+
4454
test "hd" do
4555
assert typecheck!([x = [123, :foo]], hd(x)) == dynamic(union(atom([:foo]), integer()))
4656
assert typecheck!([x = [123 | :foo]], hd(x)) == dynamic(integer())

0 commit comments

Comments
 (0)