File 0257-core_lint-Handle-repeated-variables-in-map-patterns-.patch of Package erlang

From 6626b2a4ac67631bef3144bf9eca41b5f49c3176 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Thu, 12 Apr 2018 15:05:28 +0200
Subject: [PATCH] core_lint: Handle repeated variables in map patterns
 correctly

Keys in map patterns are input variables, not pattern variables.
---
 lib/compiler/src/core_lint.erl      | 10 ++++++++--
 lib/compiler/test/compile_SUITE.erl | 24 ++++++++++++++++++++++--
 lib/compiler/test/map_SUITE.erl     | 19 +++++++++++++++++--
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index 6e2114be56..6ded8fe78f 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -491,8 +491,10 @@ pattern(#c_tuple{es=Es}, Def, Ps, St) ->
     pattern_list(Es, Def, Ps, St);
 pattern(#c_map{es=Es}, Def, Ps, St) ->
     pattern_list(Es, Def, Ps, St);
-pattern(#c_map_pair{op=#c_literal{val=exact},key=K,val=V},Def,Ps,St) ->
-    pattern_list([K,V],Def,Ps,St);
+pattern(#c_map_pair{op=#c_literal{val=exact},key=K,val=V}, Def, Ps, St) ->
+    %% The key is an input.
+    pat_map_expr(K, Def, St),
+    pattern_list([V],Def,Ps,St);
 pattern(#c_binary{segments=Ss}, Def, Ps, St0) ->
     St = pat_bin_tail_check(Ss, St0),
     pat_bin(Ss, Def, Ps, St);
@@ -555,6 +557,10 @@ pat_bit_expr(#c_binary{}, _, _Def, St) ->
 pat_bit_expr(_, _, _, St) ->
     add_error({illegal_expr,St#lint.func}, St).
 
+pat_map_expr(#c_var{name=N}, Def, St) -> expr_var(N, Def, St);
+pat_map_expr(#c_literal{}, _Def, St) -> St;
+pat_map_expr(_, _, St) -> add_error({illegal_expr,St#lint.func}, St).
+
 %% pattern_list([Var], Defined, State) -> {[PatVar],State}.
 %% pattern_list([Var], Defined, [PatVar], State) -> {[PatVar],State}.
 
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index eee5bc733f..a1de8961bd 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -1111,10 +1111,30 @@ remove_compiler_gen(M) ->
 remove_compiler_gen_1(Pair) ->
     Op0 = cerl:map_pair_op(Pair),
     Op = cerl:set_ann(Op0, []),
-    K = cerl:map_pair_key(Pair),
-    V = cerl:map_pair_val(Pair),
+    K = map_var(cerl:map_pair_key(Pair)),
+    V = map_var(cerl:map_pair_val(Pair)),
     cerl:update_c_map_pair(Pair, Op, K, V).
 
+map_var(Var) ->
+    case cerl:is_c_var(Var) of
+        true ->
+            case cerl:var_name(Var) of
+                Name when is_atom(Name) ->
+                    L = atom_to_list(Name),
+                    try list_to_integer(L) of
+                        Int ->
+                            cerl:update_c_var(Var, Int)
+                    catch
+                        error:_ ->
+                            Var
+                    end;
+                _ ->
+                    Var
+            end;
+        false ->
+            Var
+    end.
+
 %% Compile to Beam assembly language (.S) and then try to
 %% run .S through the compiler again.
 
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index f15917e3cb..3146c31c21 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -67,8 +67,10 @@
 
 	%% errors in 18
         t_register_corruption/1,
-	t_bad_update/1
+	t_bad_update/1,
 
+        %% new in OTP 21
+        t_reused_key_variable/1
     ]).
 
 suite() -> [].
@@ -120,7 +122,10 @@ all() ->
 
 	%% errors in 18
         t_register_corruption,
-        t_bad_update
+        t_bad_update,
+
+        %% new in OTP 21
+        t_reused_key_variable
     ].
 
 groups() -> [].
@@ -1980,6 +1985,16 @@ properly(Item) ->
 increase(Allows) ->
     catch fun() -> Allows end#{[] => +Allows, "warranty" => fun id/1}.
 
+t_reused_key_variable(Config) when is_list(Config) ->
+    Key = id(key),
+    Map1 = id(#{Key=>Config}),
+    Map2 = id(#{Key=>Config}),
+    case {Map1,Map2} of
+        %% core_lint treated Key as pattern variables, not input variables,
+        %% and complained about the variable being duplicated.
+        {#{Key:=Same},#{Key:=Same}} ->
+            ok
+    end.
 
 %% aux
 
-- 
2.16.3