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
17 changes: 9 additions & 8 deletions lib/elixir/src/elixir_fn.erl
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ escape({'&', _, [Pos]}, _E, Dict) when is_integer(Pos), Pos > 0 ->
Var = {list_to_atom([$x | integer_to_list(Pos)]), [], ?var_context},
{Var, orddict:store(Pos, Var, Dict)};
escape({'&', Meta, [Pos]}, E, _Dict) when is_integer(Pos) ->
form_error(Meta, E, ?MODULE, {unallowed_capture_arg, Pos});
form_error(Meta, E, ?MODULE, {invalid_arity_for_capture, Pos});
escape({'&', Meta, _} = Arg, E, _Dict) ->
form_error(Meta, E, ?MODULE, {nested_capture, Arg});
escape({Left, Meta, Right}, E, Dict0) ->
Expand Down Expand Up @@ -178,18 +178,19 @@ format_error(clauses_with_different_arities) ->
format_error(defaults_in_args) ->
"anonymous functions cannot have optional arguments";
format_error({block_expr_in_capture, Expr}) ->
io_lib:format("invalid args for &, block expressions are not allowed, got: ~ts",
io_lib:format("block expressions are not allowed inside the capture operator &, got: ~ts",
['Elixir.Macro':to_string(Expr)]);
format_error({nested_capture, Arg}) ->
io_lib:format("nested captures via & are not allowed: ~ts", ['Elixir.Macro':to_string(Arg)]);
io_lib:format("nested captures are not allowed. You cannot define a function using "
" the capture operator & inside another function defined via &. Got invalid nested "
"capture: ~ts", ['Elixir.Macro':to_string(Arg)]);
format_error({invalid_arity_for_capture, Arity}) ->
io_lib:format("invalid arity for &, expected a number between 0 and 255, got: ~b", [Arity]);
io_lib:format("capture argument &~B must be numbered between 1 and 255", [Arity]);
format_error({capture_arg_outside_of_capture, Integer}) ->
io_lib:format("unhandled &~B outside of a capture", [Integer]);
io_lib:format("capture argument &~B must be used within the capture operator &", [Integer]);
format_error({capture_arg_without_predecessor, Pos, Expected}) ->
io_lib:format("capture &~B cannot be defined without &~B", [Pos, Expected]);
format_error({unallowed_capture_arg, Integer}) ->
io_lib:format("capture &~B is not allowed", [Integer]);
io_lib:format("capture argument &~B cannot be defined without &~B "
"(you cannot skip arguments, all arguments must be numbered)", [Pos, Expected]);
format_error({invalid_args_for_capture, Arg}) ->
Message =
"invalid args for &, expected one of:\n\n"
Expand Down
18 changes: 9 additions & 9 deletions lib/elixir/test/elixir/kernel/expansion_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1084,21 +1084,21 @@ defmodule Kernel.ExpansionTest do
end

test "fails on non-continuous" do
assert_raise CompileError, ~r"capture &0 is not allowed", fn ->
assert_raise CompileError, ~r"capture argument &0 must be numbered between 1 and 255", fn ->
expand(quote(do: &foo(&0)))
end

assert_raise CompileError, ~r"capture &2 cannot be defined without &1", fn ->
assert_raise CompileError, ~r"capture argument &2 cannot be defined without &1", fn ->
expand(quote(do: & &2))
end

assert_raise CompileError, ~r"capture &255 cannot be defined without &1", fn ->
assert_raise CompileError, ~r"capture argument &255 cannot be defined without &1", fn ->
expand(quote(do: & &255))
end
end

test "fails on block" do
message = ~r"invalid args for &, block expressions are not allowed, got: 1\n2"
message = ~r"block expressions are not allowed inside the capture operator &, got: 1\n2"

assert_raise CompileError, message, fn ->
code =
Expand All @@ -1120,7 +1120,7 @@ defmodule Kernel.ExpansionTest do
end

test "fails on invalid arity" do
message = ~r"invalid arity for &, expected a number between 0 and 255, got: 256"
message = ~r"capture argument &256 must be numbered between 1 and 255"

assert_raise CompileError, message, fn ->
expand(quote(do: &Mod.fun/256))
Expand All @@ -1134,15 +1134,15 @@ defmodule Kernel.ExpansionTest do
end

test "fails on nested capture" do
assert_raise CompileError, ~r"nested captures via & are not allowed: & &1", fn ->
assert_raise CompileError, ~r"nested captures are not allowed", fn ->
expand(quote(do: &(& &1)))
end
end

test "fails on integers" do
assert_raise CompileError, ~r"unhandled &1 outside of a capture", fn ->
expand(quote(do: &1))
end
assert_raise CompileError,
~r"capture argument &1 must be used within the capture operator &",
fn -> expand(quote(do: &1)) end
end
end

Expand Down