File 3574-features-Improve-error-when-load-not-allowed.patch of Package erlang

From 51ffa165073abc18473aefcd811827bddb19654a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cons=20T=20=C3=85hs?= <cons@erlang.org>
Date: Thu, 28 Apr 2022 08:41:19 +0200
Subject: [PATCH 4/6] [features] Improve error when load not allowed

---
 erts/preloaded/src/erlang.erl   | 18 ++++++++++++------
 erts/test/lux/feature_erlc.lux  |  8 ++++----
 lib/stdlib/src/erl_features.erl | 23 ++++++++++++++---------
 3 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 3ac4677a46..afd7012a10 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -2313,14 +2313,20 @@ is_tuple(_Term) ->
 -spec load_module(Module, Binary) -> {module, Module} | {error, Reason} when
       Module :: module(),
       Binary :: binary(),
-      Reason :: badfile | not_purged | on_load | not_allowed.
+      Reason :: badfile | not_purged | on_load
+              | {features_not_allowed, [atom()]}.
 load_module(Mod, Code) ->
     try
-        Allowed = (not erlang:module_loaded(erl_features))
-            orelse erl_features:load_allowed(Code),
-        if not Allowed ->
-                {error, not_allowed};
-           true ->
+        Allowed =
+            case erlang:module_loaded(erl_features) of
+                true ->
+                    erl_features:load_allowed(Code);
+                false -> ok
+            end,
+        case Allowed of
+            {not_allowed, NotEnabled} ->
+                {error, {features_not_allowed, NotEnabled}};
+            ok ->
                 case erlang:prepare_loading(Mod, Code) of
                     {error,_}=Error ->
                         Error;
diff --git a/erts/test/lux/feature_erlc.lux b/erts/test/lux/feature_erlc.lux
index e4a092cff6..11bc8eb3e4 100644
--- a/erts/test/lux/feature_erlc.lux
+++ b/erts/test/lux/feature_erlc.lux
@@ -193,7 +193,7 @@
     # As we have not enabled any features, this load should not be
     # allowed (if we have inserted the features used in the meta chunk).
     !l(f_directives).
-    ??{error,not_allowed}
+    ??{error,{features_not_allowed,[while_expr,ifn_expr]}}
     ?$ERLPROMPT
 
     !Fs = erl_features:used(f_maybe_ifn).
@@ -205,7 +205,7 @@
     !{Mod,Bin,FName}=code:get_object_code(f_maybe_ifn).
     ?$ERLPROMPT
     !code:load_binary(Mod,FName,Bin).
-    ??{error,not_allowed}
+    ??{error,{features_not_allowed,[while_expr,ifn_expr]}}
     ?$ERLPROMPT
 
 [shell cmds]
@@ -245,7 +245,7 @@
 
 [shell erl]
     !l(f_macros).
-    ??{error,not_allowed}
+    ??{error,{features_not_allowed,[ifn_expr]}}
     ?$ERLPROMPT
 
     # Check which features were used during compilation
@@ -284,7 +284,7 @@
     # This should not be allowed as we have not enabled the feature in the
     # runtime
     !l(f_macros).
-    ??{error,not_allowed}
+    ??{error,{features_not_allowed,[ifn_expr]}}
     ?$ERLPROMPT
 
     [invoke quit-erl]
diff --git a/lib/stdlib/src/erl_features.erl b/lib/stdlib/src/erl_features.erl
index 399d048c27..5e5da948ce 100644
--- a/lib/stdlib/src/erl_features.erl
+++ b/lib/stdlib/src/erl_features.erl
@@ -390,27 +390,32 @@ keywords() ->
 set_keywords(Words) ->
     persistent_term:put({?MODULE, keywords}, Words).
 
-
--spec load_allowed(binary()) -> boolean().
+%% Check that any features used in the module are enabled in the
+%% runtime system.  If not, return
+%%  {not_allowed, <list of not enabled features>}.
+-spec load_allowed(binary()) -> ok | {not_allowed, [feature()]}.
 load_allowed(Binary) ->
     case erts_internal:beamfile_chunk(Binary, "Meta") of
         undefined ->
-            true;
+            ok;
         Meta ->
             MetaData = erlang:binary_to_term(Meta),
             case proplists:get_value(enabled_features, MetaData) of
                 undefined ->
-                    true;
+                    ok;
                 Used ->
                     Enabled = enabled(),
-                    lists:all(fun(UFtr) ->
-                                      lists:member(UFtr, Enabled)
-                              end,
-                              Used)
+                    case lists:filter(fun(UFtr) ->
+                                              not lists:member(UFtr, Enabled)
+                                      end,
+                                      Used) of
+                        [] -> ok;
+                        NotEnabled ->
+                            {not_allowed, NotEnabled}
+                    end
             end
     end.
 
-
 %% Return features used by module or beam file
 -spec used(module() | file:filename()) -> [feature()].
 used(Module) when is_atom(Module) ->
-- 
2.35.3

openSUSE Build Service is sponsored by