Skip to content

Commit e15388b

Browse files
committed
Do not leak body inference in cond, closes #12024
1 parent 4dece6c commit e15388b

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,30 @@ defmodule Module.Types.Expr do
216216
end
217217
end
218218

219+
# cond do pat -> expr end
220+
def of_expr({:cond, _meta, [[{:do, clauses}]]} = expr, _expected, stack, context) do
221+
stack = push_expr_stack(expr, stack)
222+
223+
{result, context} =
224+
reduce_ok(clauses, context, fn {:->, meta, [head, body]}, context = acc ->
225+
case of_expr(head, :dynamic, stack, context) do
226+
{:ok, _, context} ->
227+
with {:ok, _expr_type, context} <- of_expr(body, :dynamic, stack, context) do
228+
{:ok, keep_warnings(acc, context)}
229+
end
230+
231+
error ->
232+
# Skip the clause if it the head has an error
233+
if meta[:generated], do: {:ok, acc}, else: error
234+
end
235+
end)
236+
237+
case result do
238+
:ok -> {:ok, :dynamic, context}
239+
:error -> {:error, context}
240+
end
241+
end
242+
219243
# case expr do pat -> expr end
220244
def of_expr({:case, _meta, [case_expr, [{:do, clauses}]]} = expr, _expected, stack, context) do
221245
stack = push_expr_stack(expr, stack)

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,31 @@ defmodule Module.Types.ExprTest do
226226
end
227227
end
228228

229+
describe "cond" do
230+
test "do not leak body inference between clauses" do
231+
assert quoted_expr(
232+
[],
233+
cond do
234+
1 ->
235+
b = :foo
236+
b
237+
238+
2 ->
239+
b = :bar
240+
b
241+
end
242+
) == {:ok, :dynamic}
243+
244+
assert quoted_expr(
245+
[b],
246+
cond do
247+
1 -> :foo = b
248+
2 -> :bar = b
249+
end
250+
) == {:ok, :dynamic}
251+
end
252+
end
253+
229254
test "fn" do
230255
assert quoted_expr(fn :foo = b -> :foo = b end) == {:ok, :dynamic}
231256

0 commit comments

Comments
 (0)