diff options
author | José Valim <jose.valim@plataformatec.com.br> | 2018-12-20 23:16:26 +0100 |
---|---|---|
committer | José Valim <jose.valim@plataformatec.com.br> | 2018-12-20 23:16:26 +0100 |
commit | 4136f7a307dcf4c232a049ca00e9db725ab643be (patch) | |
tree | c0baa5f6e0d35984f7e86f35b2c6d3a383e0ea7f | |
parent | 7634f3f4c9380bdadd0e74eb76e9f7ae8cf27a1d (diff) | |
download | elixir-jv-cond-scope.tar.gz |
Fix cond scope and improve coverage, closes #8542jv-cond-scope
-rw-r--r-- | lib/elixir/src/elixir_erl_pass.erl | 18 | ||||
-rw-r--r-- | lib/elixir/test/elixir/fixtures/dialyzer/cond.ex | 27 | ||||
-rw-r--r-- | lib/elixir/test/elixir/kernel/dialyzer_test.exs | 5 | ||||
-rw-r--r-- | lib/elixir/test/elixir/kernel/special_forms_test.exs | 49 |
4 files changed, 90 insertions, 9 deletions
diff --git a/lib/elixir/src/elixir_erl_pass.erl b/lib/elixir/src/elixir_erl_pass.erl index ba2171897..6436d6d6f 100644 --- a/lib/elixir/src/elixir_erl_pass.erl +++ b/lib/elixir/src/elixir_erl_pass.erl @@ -109,16 +109,16 @@ translate({fn, Meta, Clauses}, S) -> %% Cond translate({'cond', CondMeta, [[{do, Clauses}]]}, S) -> - [{'->', Meta, [[Condition], Body]} = H | T] = lists:reverse(Clauses), - - Case = - case Condition of - X when is_atom(X) and (X /= false) and (X /= nil) -> - build_cond_clauses(T, Body, Meta); - _ -> - Error = {{'.', Meta, [erlang, error]}, [], [cond_clause]}, - build_cond_clauses([H | T], Error, Meta) + [{'->', Meta, [[Condition], _]} = H | T] = lists:reverse(Clauses), + + FirstMeta = + if + is_atom(Condition), Condition /= false, Condition /= nil -> ?generated(Meta); + true -> Meta end, + + Error = {{'.', Meta, [erlang, error]}, [], [cond_clause]}, + Case = build_cond_clauses([H | T], Error, FirstMeta), translate(replace_case_meta(CondMeta, Case), S); %% Case diff --git a/lib/elixir/test/elixir/fixtures/dialyzer/cond.ex b/lib/elixir/test/elixir/fixtures/dialyzer/cond.ex new file mode 100644 index 000000000..9419b9b8e --- /dev/null +++ b/lib/elixir/test/elixir/fixtures/dialyzer/cond.ex @@ -0,0 +1,27 @@ +defmodule Dialyzer.Cond do + def one_boolean do + cond do + true -> :ok + end + end + + def two_boolean do + cond do + List.flatten([]) == [] -> :ok + true -> :ok + end + end + + def one_otherwise do + cond do + :otherwise -> :ok + end + end + + def two_otherwise do + cond do + List.flatten([]) == [] -> :ok + :otherwise -> :ok + end + end +end diff --git a/lib/elixir/test/elixir/kernel/dialyzer_test.exs b/lib/elixir/test/elixir/kernel/dialyzer_test.exs index de6176b71..2ea2816e0 100644 --- a/lib/elixir/test/elixir/kernel/dialyzer_test.exs +++ b/lib/elixir/test/elixir/kernel/dialyzer_test.exs @@ -121,6 +121,11 @@ defmodule Kernel.DialyzerTest do assert_dialyze_no_warnings!(context) end + test "no warnings on cond", context do + copy_beam!(context, Dialyzer.Cond) + assert_dialyze_no_warnings!(context) + end + test "no warnings on for comprehensions with bitstrings", context do copy_beam!(context, Dialyzer.ForBitstring) assert_dialyze_no_warnings!(context) diff --git a/lib/elixir/test/elixir/kernel/special_forms_test.exs b/lib/elixir/test/elixir/kernel/special_forms_test.exs index 22f85186e..a07b00821 100644 --- a/lib/elixir/test/elixir/kernel/special_forms_test.exs +++ b/lib/elixir/test/elixir/kernel/special_forms_test.exs @@ -4,4 +4,53 @@ defmodule Kernel.SpecialFormsTest do use ExUnit.Case, async: true doctest Kernel.SpecialForms + + describe "cond" do + test "does not leak variables for one clause" do + x = 0 + + cond do + true -> + x = 1 + x + end + + assert x == 0 + end + + test "does not leak variables for one clause with non-boolean as catch-all" do + x = 0 + + cond do + :otherwise -> + x = 1 + x + end + + assert x == 0 + end + + test "does not leak variables for multiple clauses" do + x = 0 + + cond do + List.flatten([]) == [] -> + x = 1 + x + + true -> + x = 1 + x + end + + assert x == 0 + end + + test "does not warn on non-boolean as catch-all" do + cond do + List.flatten([]) == [] -> :good + :otherwise -> :also_good + end + end + end end |