[IR BE] Fix capturing of var-locals inside class/field initializers

This commit is contained in:
Roman Artemev
2019-05-30 15:12:17 +03:00
committed by romanart
parent 5686de7e09
commit beb1ce55f8
8 changed files with 121 additions and 13 deletions
@@ -17,14 +17,11 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
@@ -40,12 +37,35 @@ val sharedVariablesPhase = makeIrFilePhase(
object CoroutineIntrinsicLambdaOrigin : IrStatementOriginImpl("Coroutine intrinsic lambda")
class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass {
override fun lower(irFunction: IrFunction) {
SharedVariablesTransformer(irFunction).lowerSharedVariables()
class SharedVariablesLowering(val context: BackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) {
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFunction(declaration: IrFunction) {
declaration.acceptChildrenVoid(this)
SharedVariablesTransformer(declaration).lowerSharedVariables()
}
override fun visitField(declaration: IrField) {
declaration.acceptChildrenVoid(this)
SharedVariablesTransformer(declaration).lowerSharedVariables()
}
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
declaration.acceptChildrenVoid(this)
SharedVariablesTransformer(declaration).lowerSharedVariables()
}
})
}
private inner class SharedVariablesTransformer(val irFunction: IrFunction) {
private inner class SharedVariablesTransformer(val irDeclaration: IrDeclaration) {
private val sharedVariables = HashSet<IrVariable>()
fun lowerSharedVariables() {
@@ -56,7 +76,7 @@ class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPas
}
private fun collectSharedVariables() {
irFunction.accept(object : IrElementVisitor<Unit, IrDeclarationParent?> {
irDeclaration.accept(object : IrElementVisitor<Unit, IrDeclarationParent?> {
val relevantVars = mutableSetOf<IrVariable>()
override fun visitElement(element: IrElement, data: IrDeclarationParent?) {
@@ -93,13 +113,13 @@ class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPas
sharedVariables.add(value)
}
}
}, irFunction)
}, irDeclaration as? IrDeclarationParent ?: irDeclaration.parent)
}
private fun rewriteSharedVariables() {
val transformedSymbols = HashMap<IrValueSymbol, IrVariableSymbol>()
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
irDeclaration.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitVariable(declaration: IrVariable): IrStatement {
declaration.transformChildrenVoid(this)
@@ -113,7 +133,7 @@ class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPas
}
})
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
irDeclaration.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
@@ -0,0 +1,20 @@
fun bar(b: ()-> Unit) { b() }
class C() {
var f: Int
init {
var i = 10
bar {
i = 20
}
f = i + 1
}
}
fun box(): String {
val c = C()
if (c.f != 21) return "fail"
return "OK"
}
@@ -0,0 +1,18 @@
fun bar(b: ()-> Unit) { b() }
class C() {
val p: Int = run {
var v = 10
bar() {
v = 20
}
v + 1
}
}
fun box(): String {
val c = C()
if (c.p != 21) return "fail ${c.p}"
return "OK"
}
@@ -1834,6 +1834,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt");
}
@TestMetadata("captureVarInInitBlock.kt")
public void testCaptureVarInInitBlock() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInInitBlock.kt");
}
@TestMetadata("captureVarInPropertyInit.kt")
public void testCaptureVarInPropertyInit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInPropertyInit.kt");
}
@TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt");
@@ -1834,6 +1834,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt");
}
@TestMetadata("captureVarInInitBlock.kt")
public void testCaptureVarInInitBlock() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInInitBlock.kt");
}
@TestMetadata("captureVarInPropertyInit.kt")
public void testCaptureVarInPropertyInit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInPropertyInit.kt");
}
@TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt");
@@ -1834,6 +1834,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/callableReference/bound/boundJvmFieldInInterfaceCompanion.kt");
}
@TestMetadata("captureVarInInitBlock.kt")
public void testCaptureVarInInitBlock() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInInitBlock.kt");
}
@TestMetadata("captureVarInPropertyInit.kt")
public void testCaptureVarInPropertyInit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInPropertyInit.kt");
}
@TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt");
@@ -1369,6 +1369,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/callableReference/bound/arrayGetIntrinsic.kt");
}
@TestMetadata("captureVarInInitBlock.kt")
public void testCaptureVarInInitBlock() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInInitBlock.kt");
}
@TestMetadata("captureVarInPropertyInit.kt")
public void testCaptureVarInPropertyInit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInPropertyInit.kt");
}
@TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt");
@@ -1369,6 +1369,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/callableReference/bound/arrayGetIntrinsic.kt");
}
@TestMetadata("captureVarInInitBlock.kt")
public void testCaptureVarInInitBlock() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInInitBlock.kt");
}
@TestMetadata("captureVarInPropertyInit.kt")
public void testCaptureVarInPropertyInit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/captureVarInPropertyInit.kt");
}
@TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt");