aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src/code.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-06-04 06:14:19 +0200
committerBjörn Gustavsson <[email protected]>2018-06-04 10:41:21 +0200
commit7eb06ed5ac1687d38245db2e0aef2756cb43b1ae (patch)
tree8f796f9c5bb2ec8f059a9ba7ef37aea9fd9a6cda /lib/kernel/src/code.erl
parent7f3a501cada228c2fedbe34d0d30080e98560665 (diff)
downloadotp-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/kernel/src/code.erl')
0 files changed, 0 insertions, 0 deletions