Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions lib/elixir/src/elixir_erl_pass.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions lib/elixir/test/elixir/fixtures/dialyzer/cond.ex
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions lib/elixir/test/elixir/kernel/dialyzer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
49 changes: 49 additions & 0 deletions lib/elixir/test/elixir/kernel/special_forms_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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