IR: refuse to copy classes in InitializersLowering
This commit is contained in:
+14
-23
@@ -15,12 +15,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
|
||||
object SYNTHESIZED_INIT_BLOCK : IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
||||
|
||||
open class InitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context), BodyLoweringPass {
|
||||
|
||||
class InitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context), BodyLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
runOnFilePostfix(irFile, true)
|
||||
}
|
||||
@@ -29,31 +29,22 @@ open class InitializersLowering(context: CommonBackendContext) : InitializersLow
|
||||
if (container !is IrConstructor) return
|
||||
|
||||
val irClass = container.constructedClass
|
||||
|
||||
val instanceInitializerStatements = extractInitializers(irClass) {
|
||||
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
|
||||
}
|
||||
val block = IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
||||
// Check that the initializers contain no local classes. Deep-copying them is a disaster for code size, and liable to break randomly.
|
||||
block.accept(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) =
|
||||
element.acceptChildren(this, null)
|
||||
|
||||
override fun visitClass(declaration: IrClass) =
|
||||
throw AssertionError("class in initializer should have been moved out by LocalClassPopupLowering: ${declaration.render()}")
|
||||
}, null)
|
||||
|
||||
container.body?.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
|
||||
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
||||
.deepCopyWithSymbols(container).also {
|
||||
// Handle declarations, copied from initializers
|
||||
// Otherwise local classes inside them won't get processed.
|
||||
// Yes, there are such cases - see testData/codegen/box/properties/complexPropertyInitializer.kt
|
||||
it.acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
super.visitConstructor(declaration)
|
||||
|
||||
declaration.body?.let { lower(it, declaration) }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression =
|
||||
block.deepCopyWithSymbols(container)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -61,7 +52,7 @@ open class InitializersLowering(context: CommonBackendContext) : InitializersLow
|
||||
abstract class InitializersLoweringBase(open val context: CommonBackendContext) {
|
||||
protected fun extractInitializers(irClass: IrClass, filter: (IrDeclaration) -> Boolean) =
|
||||
// TODO What about fields that were added by lowerings? e.g. captured outer class or locals?
|
||||
ArrayList(irClass.declarations).mapNotNull { if (it is IrProperty) it.backingField else it }.filter(filter).mapNotNull {
|
||||
irClass.declarations.mapNotNull { if (it is IrProperty) it.backingField else it }.filter(filter).mapNotNull {
|
||||
when (it) {
|
||||
is IrField -> handleField(irClass, it)
|
||||
is IrAnonymousInitializer -> handleAnonymousInitializer(it)
|
||||
|
||||
@@ -504,7 +504,9 @@ private val initializersLoweringPhase = makeBodyLoweringPhase(
|
||||
::InitializersLowering,
|
||||
name = "InitializersLowering",
|
||||
description = "Merge init block and field initializers into [primary] constructor",
|
||||
prerequisite = setOf(enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase, annotationConstructorLowering)
|
||||
prerequisite = setOf(
|
||||
enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase, annotationConstructorLowering, localClassExtractionPhase
|
||||
)
|
||||
)
|
||||
|
||||
private val initializersCleanupLoweringPhase = makeDeclarationTransformerPhase(
|
||||
|
||||
+1
-1
@@ -228,7 +228,7 @@ private val initializersLoweringPhase = makeWasmModulePhase(
|
||||
::InitializersLowering,
|
||||
name = "InitializersLowering",
|
||||
description = "Merge init block and field initializers into [primary] constructor",
|
||||
prerequisite = setOf(primaryConstructorLoweringPhase)
|
||||
prerequisite = setOf(primaryConstructorLoweringPhase, localClassExtractionPhase)
|
||||
)
|
||||
|
||||
private val initializersCleanupLoweringPhase = makeWasmModulePhase(
|
||||
|
||||
Reference in New Issue
Block a user