Skip to content

Commit 57abca4

Browse files
committed
Properly handle reduce in types, closes #10224
1 parent 8e9ece0 commit 57abca4

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

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

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,19 @@ defmodule Module.Types.Expr do
277277
# for pat <- expr do expr end
278278
def of_expr({:for, _meta, args} = expr, stack, context) do
279279
stack = push_expr_stack(expr, stack)
280+
{clauses, [[{:do, block} | opts]]} = Enum.split(args, -1)
280281

281-
case reduce_ok(args, context, &for_clause(&1, stack, &2)) do
282-
{:ok, _context} -> {:ok, :dynamic, context}
283-
{:error, reason} -> {:error, reason}
282+
with {:ok, context} <- reduce_ok(clauses, context, &for_clause(&1, stack, &2)),
283+
{:ok, context} <- reduce_ok(opts, context, &for_option(&1, stack, &2)) do
284+
if opts[:reduce] do
285+
with :ok <- of_clauses(block, stack, context) do
286+
{:ok, :dynamic, context}
287+
end
288+
else
289+
with {:ok, _type, context} <- of_expr(block, stack, context) do
290+
{:ok, :dynamic, context}
291+
end
292+
end
284293
end
285294
end
286295

@@ -405,17 +414,6 @@ defmodule Module.Types.Expr do
405414
{:ok, context}
406415
end
407416

408-
defp for_option({:do, [{:->, _, [pattern, body]}]}, stack, context) do
409-
case Pattern.of_pattern(pattern, stack, context) do
410-
{:ok, _pattern_type, context} -> of_expr_context(body, stack, context)
411-
{:error, reason} -> {:error, reason}
412-
end
413-
end
414-
415-
defp for_option({:do, body}, stack, context) do
416-
of_expr_context(body, stack, context)
417-
end
418-
419417
defp with_clause({:<-, _, [left, expr]}, stack, context) do
420418
{pattern, guards} = extract_head([left])
421419

lib/elixir/test/elixir/kernel/comprehension_test.exs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,19 @@ defmodule Kernel.ComprehensionTest do
240240
assert acc == %{1 => 'olleh', 3 => 'olleh'}
241241
end
242242

243+
test "for comprehensions with matched reduce" do
244+
acc =
245+
for entry <- [1, 2, 3], reduce: {:ok, nil} do
246+
{:ok, _} ->
247+
{:ok, entry}
248+
249+
{:error, _} = error ->
250+
error
251+
end
252+
253+
assert acc == {:ok, 3}
254+
end
255+
243256
## List generators (inlined by the compiler)
244257

245258
test "list for comprehensions" do

0 commit comments

Comments
 (0)