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:
Igor Chevdar
2017-03-03 14:49:59 +03:00
parent 361e94fd1a
commit 8c1c9f5660
3 changed files with 62 additions and 9 deletions
@@ -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) {
+5
View File
@@ -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")
}