diff options
| author | Björn Gustavsson <[email protected]> | 2015-01-14 07:05:21 +0100 | 
|---|---|---|
| committer | Björn Gustavsson <[email protected]> | 2015-01-14 14:44:22 +0100 | 
| commit | 85701edb6bdfe7c616a8486542dc2ca4bd787113 (patch) | |
| tree | 15c6a1a0e1612c1dd51852dd2a15b68e942f1460 /lib/ssl/doc/src | |
| parent | a4449c481a6c887166097fd28f545876f6791625 (diff) | |
| download | otp-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 'lib/ssl/doc/src')
0 files changed, 0 insertions, 0 deletions
