aboutsummaryrefslogtreecommitdiffstats
path: root/prebuild.delete
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-01-14 07:05:21 +0100
committerBjörn Gustavsson <[email protected]>2015-01-14 14:44:22 +0100
commit85701edb6bdfe7c616a8486542dc2ca4bd787113 (patch)
tree15c6a1a0e1612c1dd51852dd2a15b68e942f1460 /prebuild.delete
parenta4449c481a6c887166097fd28f545876f6791625 (diff)
downloadotp-85701edb6bdfe7c616a8486542dc2ca4bd787113.tar.gz
otp-85701edb6bdfe7c616a8486542dc2ca4bd787113.tar.bz2
otp-85701edb6bdfe7c616a8486542dc2ca4bd787113.zip
sys_core_fold: Correct optimization of 'case'
The optimization of a 'case' statement could lead to incorrect code that would cause an exception at run-time. Here is an example to show how the optimization went wrong. Start with the following code: f({r,#{key:=Val},X}=S) -> case S of {r,_,_} -> setelement(3, Val, S) end. (The record operations have already been translated to the corresponding tuple operations.) The first step in case_opt/3 is to substitute S to obtain: f({r,#{key:=Val},X}=S) -> case {r,#{key:=Val},X} of {r,_,_} -> setelement(3, Val, S) end. After that substitution the 'case' can be simplified to: f({r,#{key:=Val},_}=S) -> case #{key:=Val} of NewVar -> setelement(3, Val, S) end. That is the result from case_opt/3. Now eval_case/2 notices that since there is only one clause left in the 'case', the 'case' can eliminated: f({r,#{key:=Val},_}=S) -> NewVar = #{key:=Val}, setelement(3, Val, S). Since the map construction may have a side effect, it was not eliminated, but assigned to a variable that is never used. The problem is that '#{key:=Val}' is fine as a pattern, but in a construction of a new map, the '=>' operator must be used. So the map construction will fail, generating an exception. As a conservative correction for a maintenance release, we will abort the 'case' optimization if the substitution into the 'case' expression is anything but data items (tuples, conses, or literals) or variables. Reported-by: Dmitry Aleksandrov
Diffstat (limited to 'prebuild.delete')
0 files changed, 0 insertions, 0 deletions