From 9cdb25737cadc6b3aa99df45a75c2d6bad3f4511 Mon Sep 17 00:00:00 2001 From: Lukasz Samson Date: Mon, 9 Nov 2026 12:03:30 +0100 Subject: [PATCH] Preserve variable versions in cond boolean optimization Assisted-by: Codex:GPT-6.1 sol --- lib/elixir/src/elixir_erl_pass.erl | 5 +++-- lib/elixir/test/elixir/kernel/macros_test.exs | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/elixir/src/elixir_erl_pass.erl b/lib/elixir/src/elixir_erl_pass.erl index 0bf6e6b0971..e95f82f6c37 100644 --- a/lib/elixir/src/elixir_erl_pass.erl +++ b/lib/elixir/src/elixir_erl_pass.erl @@ -399,8 +399,9 @@ build_truthy_clause(Meta, Condition, Body, S) -> %% In case a variable is defined to match in a condition %% but a condition returns boolean, we can replace the %% variable directly by the boolean result. -returns_boolean({'=', _, [{Var, _, Ctx}, Condition]}, {Var, _, Ctx}) when is_atom(Var), is_atom(Ctx) -> - case elixir_utils:returns_boolean(Condition) of +returns_boolean({'=', _, [{Var, VarMeta, Ctx}, Condition]}, {Var, BodyMeta, Ctx}) when is_atom(Var), is_atom(Ctx) -> + case elixir_utils:returns_boolean(Condition) andalso + lists:keyfind(version, 1, VarMeta) =:= lists:keyfind(version, 1, BodyMeta) of true -> {Condition, true}; false -> false end; diff --git a/lib/elixir/test/elixir/kernel/macros_test.exs b/lib/elixir/test/elixir/kernel/macros_test.exs index c83e0b052c9..89bbf6fbc28 100644 --- a/lib/elixir/test/elixir/kernel/macros_test.exs +++ b/lib/elixir/test/elixir/kernel/macros_test.exs @@ -17,6 +17,21 @@ defmodule Kernel.MacrosTest.Nested do end end + defmacro outer_cond do + quote do + x = :outer_value + Kernel.MacrosTest.Nested.inner_cond(x) + end + end + + defmacro inner_cond(body) do + quote do + cond do + x = is_integer(1) -> unquote(body) + end + end + end + defmacro wrap_empty_var(expr) do empty = Macro.var(:"", nil) @@ -76,6 +91,10 @@ defmodule Kernel.MacrosTest do assert Nested.value() == 1 end + test "cond preserves hygienically distinct variables in the body" do + assert Nested.outer_cond() == :outer_value + end + test "local with private macro" do assert my_private_macro() == 4 end