Turned off lowering of outer class for inner class constructors.
Constructors of inner classes already have access to their outer class through its dispatch receiver parameter.
This commit is contained in:
+37
-9
@@ -4,20 +4,22 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.callsSuper
|
import org.jetbrains.kotlin.backend.common.lower.callsSuper
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||||
|
|
||||||
@@ -83,6 +85,21 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
|
|
||||||
private fun lowerOuterThisReferences() {
|
private fun lowerOuterThisReferences() {
|
||||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
|
private fun <E> MutableList<E>.push(element: E) = this.add(element)
|
||||||
|
|
||||||
|
private fun <E> MutableList<E>.pop() = this.removeAt(size - 1)
|
||||||
|
|
||||||
|
private fun <E> MutableList<E>.peek(): E? = if (size == 0) null else this[size - 1]
|
||||||
|
|
||||||
|
private val functionsStack = mutableListOf<FunctionDescriptor>()
|
||||||
|
|
||||||
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
|
functionsStack.push(declaration.descriptor)
|
||||||
|
val result = super.visitFunction(declaration)
|
||||||
|
functionsStack.pop()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
@@ -91,12 +108,23 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
|
|
||||||
if (implicitThisClass == classDescriptor) return expression
|
if (implicitThisClass == classDescriptor) return expression
|
||||||
|
|
||||||
|
val constructorDescriptor = functionsStack.peek()!! as? ConstructorDescriptor
|
||||||
|
|
||||||
val startOffset = expression.startOffset
|
val startOffset = expression.startOffset
|
||||||
val endOffset = expression.endOffset
|
val endOffset = expression.endOffset
|
||||||
val origin = expression.origin
|
val origin = expression.origin
|
||||||
|
|
||||||
var irThis: IrExpression = IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter, origin)
|
var irThis: IrExpression
|
||||||
var innerClass = classDescriptor
|
var innerClass: ClassDescriptor
|
||||||
|
if (constructorDescriptor == null) {
|
||||||
|
innerClass = classDescriptor
|
||||||
|
irThis = IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter, origin)
|
||||||
|
} else {
|
||||||
|
// For constructor we have outer class as dispatchReceiverParameter.
|
||||||
|
innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?:
|
||||||
|
throw AssertionError("No containing class for inner class $classDescriptor")
|
||||||
|
irThis = IrGetValueImpl(startOffset, endOffset, constructorDescriptor.dispatchReceiverParameter!!, origin)
|
||||||
|
}
|
||||||
|
|
||||||
while (innerClass != implicitThisClass) {
|
while (innerClass != implicitThisClass) {
|
||||||
if (!innerClass.isInner) {
|
if (!innerClass.isInner) {
|
||||||
|
|||||||
@@ -424,6 +424,11 @@ task innerClass_noPrimaryConstructor(type: RunKonanTest) {
|
|||||||
source = "codegen/innerClass/noPrimaryConstructor.kt"
|
source = "codegen/innerClass/noPrimaryConstructor.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task innerClass_secondaryConstructor(type: RunKonanTest) {
|
||||||
|
goldValue = "42\n"
|
||||||
|
source = "codegen/innerClass/secondaryConstructor.kt"
|
||||||
|
}
|
||||||
|
|
||||||
task localClass_localHierarchy(type: RunKonanTest) {
|
task localClass_localHierarchy(type: RunKonanTest) {
|
||||||
goldValue = "OK\n"
|
goldValue = "OK\n"
|
||||||
source = "codegen/localClass/localHierarchy.kt"
|
source = "codegen/localClass/localHierarchy.kt"
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
class Outer(val x: Int) {
|
||||||
|
inner class Inner() {
|
||||||
|
inner class InnerInner() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
println(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var s: String
|
||||||
|
|
||||||
|
constructor(s: String) : this() {
|
||||||
|
this.s = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
Outer(42).Inner().InnerInner("zzz")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user