Properly handle reduce in types, closes #10224
This commit is contained in:
@@ -277,10 +277,19 @@ defmodule Module.Types.Expr do
|
||||
# for pat <- expr do expr end
|
||||
def of_expr({:for, _meta, args} = expr, stack, context) do
|
||||
stack = push_expr_stack(expr, stack)
|
||||
{clauses, [[{:do, block} | opts]]} = Enum.split(args, -1)
|
||||
|
||||
case reduce_ok(args, context, &for_clause(&1, stack, &2)) do
|
||||
{:ok, _context} -> {:ok, :dynamic, context}
|
||||
{:error, reason} -> {:error, reason}
|
||||
with {:ok, context} <- reduce_ok(clauses, context, &for_clause(&1, stack, &2)),
|
||||
{:ok, context} <- reduce_ok(opts, context, &for_option(&1, stack, &2)) do
|
||||
if opts[:reduce] do
|
||||
with :ok <- of_clauses(block, stack, context) do
|
||||
{:ok, :dynamic, context}
|
||||
end
|
||||
else
|
||||
with {:ok, _type, context} <- of_expr(block, stack, context) do
|
||||
{:ok, :dynamic, context}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -405,17 +414,6 @@ defmodule Module.Types.Expr do
|
||||
{:ok, context}
|
||||
end
|
||||
|
||||
defp for_option({:do, [{:->, _, [pattern, body]}]}, stack, context) do
|
||||
case Pattern.of_pattern(pattern, stack, context) do
|
||||
{:ok, _pattern_type, context} -> of_expr_context(body, stack, context)
|
||||
{:error, reason} -> {:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
defp for_option({:do, body}, stack, context) do
|
||||
of_expr_context(body, stack, context)
|
||||
end
|
||||
|
||||
defp with_clause({:<-, _, [left, expr]}, stack, context) do
|
||||
{pattern, guards} = extract_head([left])
|
||||
|
||||
|
||||
@@ -240,6 +240,19 @@ defmodule Kernel.ComprehensionTest do
|
||||
assert acc == %{1 => 'olleh', 3 => 'olleh'}
|
||||
end
|
||||
|
||||
test "for comprehensions with matched reduce" do
|
||||
acc =
|
||||
for entry <- [1, 2, 3], reduce: {:ok, nil} do
|
||||
{:ok, _} ->
|
||||
{:ok, entry}
|
||||
|
||||
{:error, _} = error ->
|
||||
error
|
||||
end
|
||||
|
||||
assert acc == {:ok, 3}
|
||||
end
|
||||
|
||||
## List generators (inlined by the compiler)
|
||||
|
||||
test "list for comprehensions" do
|
||||
|
||||
Reference in New Issue
Block a user