aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-01-16 09:17:03 +0100
committerBjörn Gustavsson <[email protected]>2015-01-16 09:17:03 +0100
commit4c68e41041bb178905bff490f3f77f53fef7cc17 (patch)
tree455822b658daca71ed5101958c1610ca77f41271 /lib/compiler/src
parent393f065ccdb9fc318b89893c303b428210c974ab (diff)
parent85701edb6bdfe7c616a8486542dc2ca4bd787113 (diff)
downloadotp-4c68e41041bb178905bff490f3f77f53fef7cc17.tar.gz
otp-4c68e41041bb178905bff490f3f77f53fef7cc17.tar.bz2
otp-4c68e41041bb178905bff490f3f77f53fef7cc17.zip
Merge branch 'bjorn/compiler/map-in-record-bug/OTP-12402' into maint
* bjorn/compiler/map-in-record-bug/OTP-12402: sys_core_fold: Correct optimization of 'case'
Diffstat (limited to 'lib/compiler/src')
-rw-r--r--lib/compiler/src/sys_core_fold.erl42
1 files changed, 36 insertions, 6 deletions
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 82817a987a..09716d0866 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -2072,17 +2072,47 @@ maybe_replace_var_1(E, #sub{t=Tdb}) ->
false ->
E;
true ->
- cerl_trees:map(fun(C) ->
- case cerl:is_c_alias(C) of
- false -> C;
- true -> cerl:alias_pat(C)
- end
- end, T0)
+ %% The pattern was a tuple. Now we must make sure
+ %% that the elements of the tuple are suitable. In
+ %% particular, we don't want binary or map
+ %% construction here, since that means that the
+ %% binary or map will be constructed in the 'case'
+ %% argument. That is wasteful for binaries. Even
+ %% worse is that any map pattern that use the ':='
+ %% operator will fail when used in map
+ %% construction (only the '=>' operator is allowed
+ %% when constructing a map from scratch).
+ ToData = fun coerce_to_data/1,
+ try
+ cerl_trees:map(ToData, T0)
+ catch
+ throw:impossible ->
+ %% Something unsuitable was found (map or
+ %% or binary). Keep the variable.
+ E
+ end
end;
error ->
E
end.
+%% coerce_to_data(Core) -> Core'
+%% Coerce an element originally from a pattern to an data item or or
+%% variable. Throw an 'impossible' exception if non-data Core Erlang
+%% terms such as binary construction or map construction are
+%% encountered.
+
+coerce_to_data(C) ->
+ case cerl:is_c_alias(C) of
+ false ->
+ case cerl:is_data(C) orelse cerl:is_c_var(C) of
+ true -> C;
+ false -> throw(impossible)
+ end;
+ true ->
+ coerce_to_data(cerl:alias_pat(C))
+ end.
+
%% case_opt_lit(Literal, Clauses0, LitExpr) ->
%% {ok,[],Clauses} | error
%% The current part of the case expression is a literal. That