[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 package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext 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.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.*
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.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
@@ -40,12 +37,35 @@ val sharedVariablesPhase = makeIrFilePhase(
object CoroutineIntrinsicLambdaOrigin : IrStatementOriginImpl("Coroutine intrinsic lambda") object CoroutineIntrinsicLambdaOrigin : IrStatementOriginImpl("Coroutine intrinsic lambda")
class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass { class SharedVariablesLowering(val context: BackendContext) : FileLoweringPass {
override fun lower(irFunction: IrFunction) { override fun lower(irFile: IrFile) {
SharedVariablesTransformer(irFunction).lowerSharedVariables() 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>() private val sharedVariables = HashSet<IrVariable>()
fun lowerSharedVariables() { fun lowerSharedVariables() {
@@ -56,7 +76,7 @@ class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPas
} }
private fun collectSharedVariables() { private fun collectSharedVariables() {
irFunction.accept(object : IrElementVisitor<Unit, IrDeclarationParent?> { irDeclaration.accept(object : IrElementVisitor<Unit, IrDeclarationParent?> {
val relevantVars = mutableSetOf<IrVariable>() val relevantVars = mutableSetOf<IrVariable>()
override fun visitElement(element: IrElement, data: IrDeclarationParent?) { override fun visitElement(element: IrElement, data: IrDeclarationParent?) {
@@ -93,13 +113,13 @@ class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPas
sharedVariables.add(value) sharedVariables.add(value)
} }
} }
}, irFunction) }, irDeclaration as? IrDeclarationParent ?: irDeclaration.parent)
} }
private fun rewriteSharedVariables() { private fun rewriteSharedVariables() {
val transformedSymbols = HashMap<IrValueSymbol, IrVariableSymbol>() val transformedSymbols = HashMap<IrValueSymbol, IrVariableSymbol>()
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() { irDeclaration.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitVariable(declaration: IrVariable): IrStatement { override fun visitVariable(declaration: IrVariable): IrStatement {
declaration.transformChildrenVoid(this) 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 { override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this) 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"); 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") @TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception { public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt"); 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"); 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") @TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception { public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt"); 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"); 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") @TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception { public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt"); 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"); 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") @TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception { public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt"); 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"); 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") @TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception { public void testCoercionToUnit() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt"); runTest("compiler/testData/codegen/box/callableReference/bound/coercionToUnit.kt");