File 0687-Fix-lost-exception-from-map-update.patch of Package erlang

From a5cb4f6fbca73c2d56d5d41f89ec3d268d34e36a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Thu, 2 Mar 2023 16:13:08 +0100
Subject: [PATCH] Fix lost exception from map update

Fix an unsafe optimization that would remove a map update operation
that is supposed fail. For example:

    foo() ->
        #{}#{key := value},
        ok.

Instead of raising an exception, `foo/0` would return `ok`.

Closes #6960
---
 lib/compiler/src/sys_core_fold.erl    | 28 +++++++++++++--------------
 lib/compiler/test/core_fold_SUITE.erl | 20 +++++++++++++++++--
 2 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index d79753068f..d96f3a6ae0 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -215,15 +215,15 @@ expr(#c_tuple{anno=Anno,es=Es0}=Tuple, Ctxt, Sub) ->
 	    ann_c_tuple(Anno, Es)
     end;
 expr(#c_map{anno=Anno,arg=V0,es=Es0}=Map, Ctxt, Sub) ->
-    Es = pair_list(Es0, Ctxt, descend(Map, Sub)),
+    %% Warn for useless building, but always build the map
+    %% anyway to preserve a possible exception.
     case Ctxt of
-	effect ->
-            warn_useless_building(Map, Sub),
-	    make_effect_seq(Es, Sub);
-	value ->
-	    V = expr(V0, Ctxt, Sub),
-	    ann_c_map(Anno,V,Es)
-    end;
+        effect -> warn_useless_building(Map, Sub);
+        value -> ok
+    end,
+    Es = pair_list(Es0, descend(Map, Sub)),
+    V = expr(V0, value, Sub),
+    ann_c_map(Anno, V, Es);
 expr(#c_binary{segments=Ss}=Bin0, Ctxt, Sub) ->
     %% Warn for useless building, but always build the binary
     %% anyway to preserve a possible exception.
@@ -490,14 +490,12 @@ ifes_list(_FVar, [], _Safe) ->
 expr_list(Es, Ctxt, Sub) ->
     [expr(E, Ctxt, Sub) || E <- Es].
 
-pair_list(Es, Ctxt, Sub) ->
-    [pair(E, Ctxt, Sub) || E <- Es].
+pair_list(Es, Sub) ->
+    [pair(E, Sub) || E <- Es].
 
-pair(#c_map_pair{key=K,val=V}, effect, Sub) ->
-    make_effect_seq([K,V], Sub);
-pair(#c_map_pair{key=K0,val=V0}=Pair, value=Ctxt, Sub) ->
-    K = expr(K0, Ctxt, Sub),
-    V = expr(V0, Ctxt, Sub),
+pair(#c_map_pair{key=K0,val=V0}=Pair, Sub) ->
+    K = expr(K0, value, Sub),
+    V = expr(V0, value, Sub),
     Pair#c_map_pair{key=K,val=V}.
 
 bitstr_list(Es, Sub) ->
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 4da55bed2e..0bdcfab5b7 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -29,7 +29,8 @@
 	 no_no_file/1,configuration/1,supplies/1,
          redundant_stack_frame/1,export_from_case/1,
          empty_values/1,cover_letrec_effect/1,
-         receive_effect/1,nested_lets/1]).
+         receive_effect/1,nested_lets/1,
+         map_effect/1]).
 
 -export([foo/0,foo/1,foo/2,foo/3]).
 
@@ -50,8 +51,8 @@ groups() ->
        no_no_file,configuration,supplies,
        redundant_stack_frame,export_from_case,
        empty_values,cover_letrec_effect,
-       receive_effect,nested_lets]}].
-
+       receive_effect,nested_lets,
+       map_effect]}].
 
 init_per_suite(Config) ->
     test_lib:recompile(?MODULE),
@@ -778,5 +779,22 @@ nested_lets_2(X, 0) ->
 nested_lets_2_f(_) ->
     ok.
 
+map_effect(_Config) ->
+    {'EXIT',{{badkey,key},_}} = catch map_effect_1(),
+
+    {'EXIT',{{badkey,key},_}} = catch map_effect_2(#{}),
+    {'EXIT',{{badmap,no_map},_}} = catch map_effect_2(no_map),
+
+    ok.
+
+map_effect_1() ->
+    #{}#{key := value},
+    ok.
+
+map_effect_2(Map) ->
+    Map#{key := value},
+    ok.
+
 %%% Common utility functions.
+
 id(I) -> I.
-- 
2.35.3

openSUSE Build Service is sponsored by