[IR BE] Fix capturing of var-locals inside class/field initializers
This commit is contained in:
+33
-13
@@ -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)
|
||||||
|
|
||||||
|
|||||||
+20
@@ -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"
|
||||||
|
}
|
||||||
+18
@@ -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"
|
||||||
|
}
|
||||||
+10
@@ -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");
|
||||||
|
|||||||
+10
@@ -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");
|
||||||
|
|||||||
+10
@@ -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");
|
||||||
|
|||||||
Generated
+10
@@ -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");
|
||||||
|
|||||||
+10
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user