diff options
author | felipe stival <14948182+v0idpwn@users.noreply.github.com> | 2022-01-06 01:48:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-06 00:48:04 +0100 |
commit | 953c730cc8addd23a079dfa3a4850a40d299c2a0 (patch) | |
tree | a11a3884bf56d424537f2bbf57118fe6d1933f92 | |
parent | 64ac646a24f8e0d7f0eb6f0ae2152a578df5cebe (diff) | |
download | elixir-953c730cc8addd23a079dfa3a4850a40d299c2a0.tar.gz |
EEP 52: Allow pins inside map keys in matches (#11544)
-rw-r--r-- | lib/elixir/src/elixir_map.erl | 11 | ||||
-rw-r--r-- | lib/elixir/test/elixir/kernel/expansion_test.exs | 17 | ||||
-rw-r--r-- | lib/elixir/test/elixir/module/types/map_test.exs | 7 |
3 files changed, 16 insertions, 19 deletions
diff --git a/lib/elixir/src/elixir_map.erl b/lib/elixir/src/elixir_map.erl index 3da517ae8..560b7a437 100644 --- a/lib/elixir/src/elixir_map.erl +++ b/lib/elixir/src/elixir_map.erl @@ -60,10 +60,10 @@ clean_struct_key_from_map_assocs(Meta, Assocs, E) -> Assocs end. -validate_match_key(Meta, {'^', _, [{Name, _, Context}]}, E) when is_atom(Name), is_atom(Context) -> - form_error(Meta, E, ?MODULE, {invalid_pin_in_map_key_match, Name}); validate_match_key(Meta, {Name, _, Context}, E) when is_atom(Name), is_atom(Context) -> form_error(Meta, E, ?MODULE, {invalid_variable_in_map_key_match, Name}); +validate_match_key(_, {'^', _, [{Name, _, Context}]}, _) when is_atom(Name), is_atom(Context) -> + ok; validate_match_key(_, {'%{}', _, [_ | _]}, _) -> ok; validate_match_key(Meta, {Left, _, Right}, E) -> @@ -102,8 +102,6 @@ is_literal(_) -> true. validate_kv(Meta, KV, Original, #{context := Context} = E) -> lists:foldl(fun - ({{'^', _, [_]}, _}, {Index, Used}) -> - {Index + 1, Used}; ({K, _V}, {Index, Used}) -> (Context == match) andalso validate_match_key(Meta, K, E), NewUsed = validate_not_repeated(Meta, K, Used, E), @@ -202,11 +200,6 @@ format_error({invalid_struct_name_in_match, Expr}) -> format_error({invalid_struct_name, Expr}) -> Message = "expected struct name to be a compile time atom or alias, got: ~ts", io_lib:format(Message, ['Elixir.Macro':to_string(Expr)]); -format_error({invalid_pin_in_map_key_match, Name}) -> - Message = - "cannot use pin operator ^~ts inside a data structure as a map key in a pattern. " - "The pin operator can only be used as the whole key", - io_lib:format(Message, [Name]); format_error({invalid_variable_in_map_key_match, Name}) -> Message = "cannot use variable ~ts as map key inside a pattern. Map keys in patterns can only be literals " diff --git a/lib/elixir/test/elixir/kernel/expansion_test.exs b/lib/elixir/test/elixir/kernel/expansion_test.exs index 360058d4a..8282a094d 100644 --- a/lib/elixir/test/elixir/kernel/expansion_test.exs +++ b/lib/elixir/test/elixir/kernel/expansion_test.exs @@ -475,16 +475,13 @@ defmodule Kernel.ExpansionTest do assert expand(ast) == ast - assert_raise CompileError, - ~r"cannot use pin operator \^x inside a data structure as a map key in a pattern", - fn -> - expand( - quote do - x = 1 - %{{^x} => 1} = %{} - end - ) - end + ast = + quote do + x = 1 + %{{^x} => 1} = %{{1} => 1} + end + + assert expand(ast) == ast assert_raise CompileError, ~r"cannot use variable x as map key inside a pattern", fn -> expand(quote(do: %{x => 1} = %{})) diff --git a/lib/elixir/test/elixir/module/types/map_test.exs b/lib/elixir/test/elixir/module/types/map_test.exs index f416d77da..5324c8453 100644 --- a/lib/elixir/test/elixir/module/types/map_test.exs +++ b/lib/elixir/test/elixir/module/types/map_test.exs @@ -160,6 +160,13 @@ defmodule Module.Types.MapTest do ) ) == {:ok, {:map, [{:required, {:atom, :a}, {:atom, :b}}]}} + assert quoted_expr( + ( + a = :a + %{{^a, :b} => :c} = %{{:a, :b} => :c} + ) + ) == {:ok, {:map, [{:required, {:tuple, 2, [{:atom, :a}, {:atom, :b}]}, {:atom, :c}}]}} + assert {:error, {:unable_unify, {{:map, [{:required, {:atom, :c}, {:atom, :d}}]}, |