diff options
author | Björn Gustavsson <[email protected]> | 2015-01-16 09:17:03 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2015-01-16 09:17:03 +0100 |
commit | 4c68e41041bb178905bff490f3f77f53fef7cc17 (patch) | |
tree | 455822b658daca71ed5101958c1610ca77f41271 /lib/compiler/src | |
parent | 393f065ccdb9fc318b89893c303b428210c974ab (diff) | |
parent | 85701edb6bdfe7c616a8486542dc2ca4bd787113 (diff) | |
download | otp-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.erl | 42 |
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 |