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