Skip to content

Commit 73adf72

Browse files
committed
Do not leak variables from conditional vars, closes #15074
1 parent 22006fd commit 73adf72

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

lib/elixir/lib/module/types/of.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,11 @@ defmodule Module.Types.Of do
197197
Reduces conditional variables collected separately.
198198
"""
199199
def reduce_conditional_vars([{vars, cond} | vars_conds], expr, stack, context) do
200+
%{vars: pre_vars} = context
201+
200202
Enum.reduce(Map.keys(cond), context, fn version, context ->
201-
if Enum.all?(vars_conds, fn {_vars, cond} -> is_map_key(cond, version) end) do
203+
if is_map_key(pre_vars, version) and
204+
Enum.all?(vars_conds, fn {_vars, cond} -> is_map_key(cond, version) end) do
202205
%{^version => %{type: type}} = vars
203206

204207
type =

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

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -530,25 +530,6 @@ defmodule Module.Types.ExprTest do
530530
"""
531531
end
532532

533-
test "capture a function with non atoms" do
534-
assert typeerror!([<<x::integer>>], &x.foo_bar/2) ==
535-
~l"""
536-
expected a module (an atom) when invoking foo_bar/2 in expression:
537-
538-
&x.foo_bar/2
539-
540-
but got type:
541-
542-
integer()
543-
544-
where "x" was given the type:
545-
546-
# type: integer()
547-
# from: types_test.ex:LINE-1
548-
<<x::integer>>
549-
"""
550-
end
551-
552533
test "computes union of all combinations" do
553534
assert typecheck!(
554535
[condition, arg],
@@ -604,6 +585,22 @@ defmodule Module.Types.ExprTest do
604585
end
605586
"""
606587
end
588+
589+
test "calling a function with conditional variables excluside to the application" do
590+
assert typecheck!(
591+
[condition, arg],
592+
(
593+
mod = if condition, do: Integer, else: Float
594+
595+
mod.parse(
596+
(
597+
query = "+" <> arg
598+
String.trim_trailing(query)
599+
)
600+
)
601+
)
602+
) == dynamic()
603+
end
607604
end
608605

609606
describe "remote capture" do
@@ -616,6 +613,25 @@ defmodule Module.Types.ExprTest do
616613
assert typecheck!(&Module.Types.ExprTest.__ex_unit__/1) == dynamic(fun(1))
617614
assert typecheck!([x], &x.something/1) == dynamic(fun(1))
618615
end
616+
617+
test "capture a function with non atoms" do
618+
assert typeerror!([<<x::integer>>], &x.foo_bar/2) ==
619+
~l"""
620+
expected a module (an atom) when invoking foo_bar/2 in expression:
621+
622+
&x.foo_bar/2
623+
624+
but got type:
625+
626+
integer()
627+
628+
where "x" was given the type:
629+
630+
# type: integer()
631+
# from: types_test.ex:LINE-1
632+
<<x::integer>>
633+
"""
634+
end
619635
end
620636

621637
describe "binaries" do

0 commit comments

Comments
 (0)