File 0210-compiler-Disallow-multiple-_-as-record-field-key.patch of Package erlang

From 42a8fee1e4f4c7545a2d34c5b2bc4df1fde3bf59 Mon Sep 17 00:00:00 2001
From: Hans Bolinder <hasse@erlang.org>
Date: Mon, 2 Mar 2020 15:19:11 +0100
Subject: [PATCH 2/2] compiler: Disallow multiple '_' as record field key

There is no way to fix:

  -record(r, {f, g}).
  f(#r{_ = V1, _ = V2, f = 17}) -> {V1, V2}.

Compilation with 'E' showed why:

  f({r, 17, V1}) ->
      {V1, V2}.

This case is similar to the last commit, "Disallow '_' as record field
key without effect", as the second initialization has no effect.
---
 lib/stdlib/src/erl_lint.erl        |  7 +++--
 lib/stdlib/test/erl_lint_SUITE.erl | 52 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 7b86015594..fee0a1bf05 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2752,9 +2752,12 @@ check_field({record_field,Lf,{atom,La,F},Val}, Name, Fields,
                  error -> {[],add_error(La, {undefined_field,Name,F}, St)}
              end}
     end;
-check_field({record_field,_Lf,{var,_La,'_'},Val}, _Name, _Fields,
+check_field({record_field,_Lf,{var,La,'_'=F},Val}, _Name, _Fields,
             Vt, St, Sfs, CheckFun) ->
-    {Sfs,CheckFun(Val, Vt, St)};
+    case member(F, Sfs) of
+        true -> {Sfs,{[],add_error(La, bad_multi_field_init, St)}};
+        false -> {[F|Sfs],CheckFun(Val, Vt, St)}
+    end;
 check_field({record_field,_Lf,{var,La,V},_Val}, Name, _Fields,
             Vt, St, Sfs, _CheckFun) ->
     {Sfs,{Vt,add_error(La, {field_name_is_variable,Name,V}, St)}}.
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 0533aef4d2..92667bf6e5 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -4340,6 +4340,10 @@ removed(Config) when is_list(Config) ->
     ok.
 
 otp_16516(Config) when is_list(Config) ->
+    one_multi_init(Config),
+    several_multi_inits(Config).
+
+one_multi_init(Config) ->
     "'_' initializes no omitted fields" =
         format_error(bad_multi_field_init),
     Ts = [{otp_16516_1,
@@ -4380,6 +4384,54 @@ otp_16516(Config) when is_list(Config) ->
            []}],
     [] = run(Config, Ts).
 
+several_multi_inits(Config) ->
+    Ts = [{otp_16516_4,
+           <<"-record(r, {f, g}).
+              t(#r{f = 17, _ = V1,
+                           _ = V2}) ->
+                  {V1, V2}.
+              u(#r{_ = V1, f = 17,
+                   _ = V2}) ->
+                  {V1, V2}.
+              v(#r{_ = V1, f = 17}) ->
+                  V1.
+             ">>,
+           [],
+           {errors,[{3,erl_lint,bad_multi_field_init},
+                    {4,erl_lint,{unbound_var,'V1'}},
+                    {4,erl_lint,{unbound_var,'V2'}},
+                    {6,erl_lint,bad_multi_field_init},
+                    {7,erl_lint,{unbound_var,'V1'}},
+                    {7,erl_lint,{unbound_var,'V2'}}],[]}},
+          {otp_16516_5,
+           <<"-record(r, {f, g}).
+              t(V1, V2) ->
+                  #r{_ = V1, f = 3,
+                     _ = V2}.
+              u(V1, V2) ->
+                  #r{_ = V1,
+                     _ = V2, f = 3}.
+             ">>,
+           [],
+           {error,[{4,erl_lint,bad_multi_field_init},
+                   {7,erl_lint,bad_multi_field_init}],
+            [{2,erl_lint,{unused_var,'V2'}},{5,erl_lint,{unused_var,'V2'}}]}},
+          {otp_16516_6,
+           <<"-record(r, {f, g}).
+              t(V1, V2) when #r{_ = V1, f = 3,
+                                _ = V2} =:= #r{} ->
+                  a.
+              u(V1, V2) when #r{_ = V1, f = 3,
+                                _ = V2} =:= #r{} ->
+                  a.
+             ">>,
+           [],
+           {error,[{3,erl_lint,bad_multi_field_init},
+                   {6,erl_lint,bad_multi_field_init}],
+            [{2,erl_lint,{unused_var,'V2'}},
+             {5,erl_lint,{unused_var,'V2'}}]}}],
+    [] = run(Config, Ts).
+
 format_error(E) ->
     lists:flatten(erl_lint:format_error(E)).
 
-- 
2.16.4

openSUSE Build Service is sponsored by