Skip to content

Commit 9726dad

Browse files
committed
Raise CompileError in case of duplicated clauses given for try
1 parent 136c036 commit 9726dad

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

lib/elixir/src/elixir_exp_clauses.erl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ do_receive(Meta, {Key, _}, _Acc, E) ->
107107
'try'(Meta, KV, E) when not is_list(KV) ->
108108
compile_error(Meta, ?m(E, file), "invalid arguments for try");
109109
'try'(Meta, KV, E) ->
110+
RaiseError = fun(Kind) ->
111+
compile_error(Meta, ?m(E, file), "duplicated ~ts clauses given for try", [Kind])
112+
end,
113+
ok = assert_at_most_once('do', KV, 0, RaiseError),
114+
ok = assert_at_most_once('rescue', KV, 0, RaiseError),
115+
ok = assert_at_most_once('catch', KV, 0, RaiseError),
116+
ok = assert_at_most_once('else', KV, 0, RaiseError),
117+
ok = assert_at_most_once('after', KV, 0, RaiseError),
110118
{lists:map(fun(X) -> do_try(Meta, X, E) end, KV), E}.
111119

112120
do_try(_Meta, {'do', Expr}, E) ->
@@ -214,3 +222,11 @@ expand_without_export(Meta, Kind, Fun, {Key, Clauses}, E) when is_list(Clauses)
214222
{Key, lists:map(Transformer, Clauses)};
215223
expand_without_export(Meta, Kind, _Fun, {Key, _}, E) ->
216224
compile_error(Meta, ?m(E, file), "expected -> clauses for ~ts in ~ts", [Key, Kind]).
225+
226+
assert_at_most_once(_Kind, [], _Count, _Fun) -> ok;
227+
assert_at_most_once(Kind, [{Kind, _} | _], 1, ErrorFun) ->
228+
ErrorFun(Kind);
229+
assert_at_most_once(Kind, [{Kind, _} | Rest], Count, Fun) ->
230+
assert_at_most_once(Kind, Rest, Count + 1, Fun);
231+
assert_at_most_once(Kind, [_ | Rest], Count, Fun) ->
232+
assert_at_most_once(Kind, Rest, Count, Fun).

lib/elixir/test/elixir/kernel/expansion_test.exs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,28 @@ defmodule Kernel.ExpansionTest do
413413
end
414414
end
415415

416+
test "try: expects at most one clause" do
417+
assert_raise CompileError, ~r"duplicated do clauses given for try", fn ->
418+
expand(quote(do: try(do: e, do: f)))
419+
end
420+
421+
assert_raise CompileError, ~r"duplicated rescue clauses given for try", fn ->
422+
expand(quote(do: (try do e rescue x -> x rescue y -> y end)))
423+
end
424+
425+
assert_raise CompileError, ~r"duplicated after clauses given for try", fn ->
426+
expand(quote(do: (try do e after x = y after x = y end)))
427+
end
428+
429+
assert_raise CompileError, ~r"duplicated else clauses given for try", fn ->
430+
expand(quote(do: (try do e else x -> x else y -> y end)))
431+
end
432+
433+
assert_raise CompileError, ~r"duplicated catch clauses given for try", fn ->
434+
expand(quote(do: (try do e catch x -> x catch y -> y end)))
435+
end
436+
end
437+
416438
## Binaries
417439

418440
test "bitstrings: size * unit" do

0 commit comments

Comments
 (0)