Skip to content

Commit e3f017d

Browse files
committed
Deal with lists inside tuples inside lists
1 parent 69a95a8 commit e3f017d

File tree

2 files changed

+32
-16
lines changed

2 files changed

+32
-16
lines changed

lib/elixir/lib/module/types/pattern.ex

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,13 @@ defmodule Module.Types.Pattern do
148148
[var, {:arg, index, expected, expr} | path], {var_changed?, context} ->
149149
actual = Enum.fetch!(types, index)
150150

151-
case of_pattern_var(path, actual, info, context) do
152-
{:ok, type} ->
151+
case of_pattern_var(path, actual, true, info, context) do
152+
{type, reachable_var?} ->
153153
case Of.refine_var(var, type, expr, stack, context) do
154154
{:ok, type, context} ->
155-
{var_changed? or current_type == nil or not equal?(current_type, type),
156-
context}
155+
{var_changed? or
156+
(reachable_var? and
157+
(current_type == nil or not equal?(current_type, type))), context}
157158

158159
{:error, _type, context} ->
159160
throw({types, context})
@@ -226,44 +227,46 @@ defmodule Module.Types.Pattern do
226227
end
227228
end
228229

229-
defp of_pattern_var([], type, _info, _context) do
230-
{:ok, type}
230+
defp of_pattern_var([], type, reachable_var?, _info, _context) do
231+
{type, reachable_var?}
231232
end
232233

233-
defp of_pattern_var([{:elem, index} | rest], type, info, context) when is_integer(index) do
234+
defp of_pattern_var([{:elem, index} | rest], type, reachable_var?, info, context)
235+
when is_integer(index) do
234236
case tuple_fetch(type, index) do
235-
{_optional?, type} -> of_pattern_var(rest, type, info, context)
237+
{_optional?, type} -> of_pattern_var(rest, type, reachable_var?, info, context)
236238
_reason -> :error
237239
end
238240
end
239241

240-
defp of_pattern_var([{:key, field} | rest], type, info, context) when is_atom(field) do
242+
defp of_pattern_var([{:key, field} | rest], type, reachable_var?, info, context)
243+
when is_atom(field) do
241244
case map_fetch(type, field) do
242-
{_optional?, type} -> of_pattern_var(rest, type, info, context)
245+
{_optional?, type} -> of_pattern_var(rest, type, reachable_var?, info, context)
243246
_reason -> :error
244247
end
245248
end
246249

247250
# TODO: Implement domain key types
248-
defp of_pattern_var([{:key, _key} | rest], _type, info, context) do
249-
of_pattern_var(rest, dynamic(), info, context)
251+
defp of_pattern_var([{:key, _key} | rest], _type, reachable_var?, info, context) do
252+
of_pattern_var(rest, dynamic(), reachable_var?, info, context)
250253
end
251254

252-
defp of_pattern_var([{:head, counter} | rest], type, info, context) do
255+
defp of_pattern_var([{:head, counter} | rest], type, _reachable_var?, info, context) do
253256
case list_hd(type) do
254257
{_, head} ->
255258
tree = Map.fetch!(info, -counter)
256259
type = intersection(of_pattern_tree(tree, context), head)
257-
of_pattern_var(rest, type, info, context)
260+
of_pattern_var(rest, type, false, info, context)
258261

259262
_ ->
260263
:error
261264
end
262265
end
263266

264-
defp of_pattern_var([:tail | rest], type, info, context) do
267+
defp of_pattern_var([:tail | rest], type, reachable_var?, info, context) do
265268
case list_tl(type) do
266-
{_, tail} -> of_pattern_var(rest, tail, info, context)
269+
{_, tail} -> of_pattern_var(rest, tail, reachable_var?, info, context)
267270
_ -> :error
268271
end
269272
end

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,19 @@ defmodule Module.Types.PatternTest do
182182
assert typecheck!([x = [1, 2, 3] ++ y, y = [1.0, 2.0, 3.0]], x) ==
183183
dynamic(non_empty_list(union(integer(), float())))
184184
end
185+
186+
test "with lists inside tuples inside lists" do
187+
assert typecheck!([[node_1 = {[arg]}, node_2 = {[arg]}]], {node_1, node_2, arg})
188+
|> equal?(
189+
dynamic(
190+
tuple([
191+
tuple([non_empty_list(term())]),
192+
tuple([non_empty_list(term())]),
193+
term()
194+
])
195+
)
196+
)
197+
end
185198
end
186199

187200
describe "binaries" do

0 commit comments

Comments
 (0)