diff --git a/lib/elixir/src/elixir_fn.erl b/lib/elixir/src/elixir_fn.erl index cf1e7ea1e73..7085cda7e42 100644 --- a/lib/elixir/src/elixir_fn.erl +++ b/lib/elixir/src/elixir_fn.erl @@ -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) -> @@ -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" diff --git a/lib/elixir/test/elixir/kernel/expansion_test.exs b/lib/elixir/test/elixir/kernel/expansion_test.exs index 3ec2d0de6ee..fb62e77f407 100644 --- a/lib/elixir/test/elixir/kernel/expansion_test.exs +++ b/lib/elixir/test/elixir/kernel/expansion_test.exs @@ -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 = @@ -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)) @@ -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