diff options
author | Björn Gustavsson <[email protected]> | 2018-06-04 06:14:19 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2018-06-04 10:41:21 +0200 |
commit | 7eb06ed5ac1687d38245db2e0aef2756cb43b1ae (patch) | |
tree | 8f796f9c5bb2ec8f059a9ba7ef37aea9fd9a6cda /lib/compiler/test/compiler.cover | |
parent | 7f3a501cada228c2fedbe34d0d30080e98560665 (diff) | |
download | otp-7eb06ed5ac1687d38245db2e0aef2756cb43b1ae.tar.gz otp-7eb06ed5ac1687d38245db2e0aef2756cb43b1ae.tar.bz2 otp-7eb06ed5ac1687d38245db2e0aef2756cb43b1ae.zip |
sys_core_fold: Fix name capture problem
sys_core_fold could do unsafe transformations on the
code from the old inliner (invoked using the compiler
option `{inline,[{F/A}]}` to request inlining of specific
functions).
To explain the bug, let's first look at an example that
sys_core_fold handles correctly. Consider this code:
'foo'/2 =
fun (Arg1,Arg2) ->
let <B> = Arg2
in let <A,B> = <B,Arg1>
in {A,B}
In this example, the lets can be completely eliminated,
since the arguments for the lets are variables (as opposed
to expressions). Since the variable B is rebound in the
inner let, `sys_core_fold` must take special care when
doing the substitutions.
Here is the correct result:
'foo'/2 =
fun (Arg1, Arg2) ->
{Arg2,Arg1}
Consider a slight modifictation of the example:
'bar'/2 =
fun (Arg1,Arg2) ->
let <B> = [Arg2]
in let <A,B> = <B,[Arg1]>
in {A,B}
Here some of the arguments for the lets are expressions, so
the lets must be kept. sys_core_fold does not handle this
example correctly:
'bar'/2 =
fun (Arg1,Arg2) ->
let <B> = [Arg2]
in let <B> = [Arg1]
in {B,B}
In the inner let, the variable A has been eliminated and
replaced with the variable B in the body (the first B in
the tuple). Since the B in the outer let is never used,
the outer let will be eliminated, giving:
'bar'/2 =
fun (Arg1,Arg2) ->
let <B> = [Arg1]
in {B,B}
To handle this example correctly, sys_core_fold must
rename the variable B in the inner let like this to
avoid capturing B:
'bar'/2 =
fun (Arg1,Arg2) ->
let <B> = [Arg2]
in let <NewName> = [Arg1]
in {B,NewName}
(Note: The `v3_kernel` pass alreday handles those examples correctly
in case `sys_core_fold` has been disabled.)
Diffstat (limited to 'lib/compiler/test/compiler.cover')
0 files changed, 0 insertions, 0 deletions