From b4862b2187c60394ab8a7fbbd52568c07596a783 Mon Sep 17 00:00:00 2001 From: sabiwara Date: Thu, 11 Jun 2026 08:52:56 +0900 Subject: [PATCH] Properly reset variables between cond clauses --- lib/elixir/lib/module/types/expr.ex | 7 +++---- lib/elixir/test/elixir/module/types/expr_test.exs | 12 ++++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/elixir/lib/module/types/expr.ex b/lib/elixir/lib/module/types/expr.ex index dc6c0638e67..e1ded6d88da 100644 --- a/lib/elixir/lib/module/types/expr.ex +++ b/lib/elixir/lib/module/types/expr.ex @@ -347,9 +347,9 @@ defmodule Module.Types.Expr do cache_result(meta, stack, context, fn -> {body_type, acc_context} = reduce_non_empty(clauses, {none(), context}, fn - {:->, meta, [[head], body]}, {acc, context}, last? -> + {:->, meta, [[head], body]}, {acc, initial_context}, last? -> {head_type, context} = - of_expr(head, term(), head, %{stack | reverse_arrow: :cache}, context) + of_expr(head, term(), head, %{stack | reverse_arrow: :cache}, initial_context) context = maybe_always_or_never_match_cond(head_type, head, meta, stack, context, last?) @@ -360,9 +360,8 @@ defmodule Module.Types.Expr do # Keep the context except the warnings, and compute the body truthy_context = reset_warnings(truthy_context, context) {body_type, body_context} = of_expr(body, expected, expr, stack, truthy_context) - # Reset the context vars to the head definition to compute the falsy type - context = Of.reset_vars(body_context, context) + context = Of.reset_vars(body_context, initial_context) context = if last? do diff --git a/lib/elixir/test/elixir/module/types/expr_test.exs b/lib/elixir/test/elixir/module/types/expr_test.exs index 5963b6b2364..2857fef45a0 100644 --- a/lib/elixir/test/elixir/module/types/expr_test.exs +++ b/lib/elixir/test/elixir/module/types/expr_test.exs @@ -3450,5 +3450,17 @@ defmodule Module.Types.ExprTest do ) ) == dynamic() or binary() end + + defguard is_pair(x) when is_tuple(x) and tuple_size(x) == 2 + + test "cond with custom guard" do + assert typecheck!( + [x], + cond do + is_pair(x) -> :pair + is_atom(x) -> :atom + end + ) == atom([:pair, :atom]) + end end end