diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt index 9af0994cdee..bc2f1b16d91 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt @@ -19,14 +19,103 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.classifierOrNull -import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.ir.util.transformFlat +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +internal class OuterThisLowering(val context: Context) : ClassLoweringPass { + override fun lower(irClass: IrClass) { + if (!irClass.isInner) return + irClass.transformChildrenVoid(Transformer(irClass, irClass)) + } + + fun lower(irFunction: IrFunction) { + var parent = irFunction.parent + var irClass: IrClass? = null + while (parent !is IrPackageFragment) { + irClass = parent as? IrClass + if (irClass != null) break + parent = (parent as IrDeclaration).parent + } + if (irClass == null || !irClass.isInner) return + + irFunction.body?.transformChildrenVoid(Transformer(irClass, irFunction)) + } + + private inner class Transformer(val irClass: IrClass, val container: IrDeclaration) : IrElementTransformerVoidWithContext() { + override fun visitClassNew(declaration: IrClass): IrStatement { + // Skip nested. + return declaration + } + + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid(this) + + val implicitThisClass = (expression.symbol.owner.parent as? IrClass) ?: return expression + + if (implicitThisClass == irClass) return expression + + val parentScopeSymbols = listOf(container.symbol) + allScopes.map { it.scope.scopeOwnerSymbol } + var functionSymbol: IrFunctionSymbol? = null + for (i in parentScopeSymbols.size - 1 downTo 0) { + val currentSymbol = parentScopeSymbols[i] as? IrFunctionSymbol ?: break + functionSymbol = currentSymbol + } + if (functionSymbol == null) return expression + + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val origin = expression.origin + + var irThis: IrExpression + var innerClass: IrClass + if ((functionSymbol as? IrConstructorSymbol)?.owner?.parentAsClass == irClass) { + // For constructor we have outer class as dispatchReceiverParameter. + innerClass = irClass.parent as? IrClass ?: error("No containing class for inner class ${irClass.render()}") + val thisParameter = functionSymbol.owner.dispatchReceiverParameter!! + irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin) + } else { + innerClass = irClass + + val currentFunctionReceiver = functionSymbol.owner.dispatchReceiverParameter + val thisParameter = + if (currentFunctionReceiver?.type?.classifierOrNull == irClass.symbol) + currentFunctionReceiver + else + irClass.thisReceiver!! + + irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin) + } + + while (innerClass != implicitThisClass) { + if (!innerClass.isInner) { + // Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is - + // should be transformed by closures conversion. + return expression + } + + val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass) + irThis = IrGetFieldImpl( + startOffset, endOffset, + outerThisField.symbol, outerThisField.type, + irThis, + origin + ) + + val outer = innerClass.parent + innerClass = outer as? IrClass + ?: throw AssertionError("Unexpected containing declaration for inner class ${innerClass.dump()}: $outer") + } + + return irThis + } + } +} + internal class InnerClassLowering(val context: Context) : ClassLoweringPass { override fun lower(irClass: IrClass) { + OuterThisLowering(context).lower(irClass) InnerClassTransformer(irClass).lowerInnerClass() } @@ -45,7 +134,6 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { if (!irClass.isInner) return createOuterThisField() - lowerOuterThisReferences() lowerConstructors() } @@ -85,73 +173,6 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { return irConstructor } - - private fun lowerOuterThisReferences() { - irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { - override fun visitClassNew(declaration: IrClass): IrStatement { - // Skip nested. - return declaration - } - - override fun visitGetValue(expression: IrGetValue): IrExpression { - expression.transformChildrenVoid(this) - - val implicitThisClass = (expression.symbol.owner.parent as? IrClass) ?: return expression - - if (implicitThisClass == irClass) return expression - - val constructorSymbol = currentFunction!!.scope.scopeOwnerSymbol as? IrConstructorSymbol - - val startOffset = expression.startOffset - val endOffset = expression.endOffset - val origin = expression.origin - - var irThis: IrExpression - var innerClass: IrClass - if (constructorSymbol == null || constructorSymbol.owner.parentAsClass != irClass) { - innerClass = irClass - val currentIrFunction = currentFunction!!.scope.scopeOwnerSymbol.owner as IrFunction - - val currentFunctionReceiver = currentIrFunction.dispatchReceiverParameter - val thisParameter = - if (currentFunctionReceiver?.type?.classifierOrNull == irClass.symbol) - currentFunctionReceiver - else - irClass.thisReceiver!! - - irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin) - } else { - // For constructor we have outer class as dispatchReceiverParameter. - innerClass = irClass.parent as? IrClass ?: - throw AssertionError("No containing class for inner class ${irClass.dump()}") - val thisParameter = constructorSymbol.owner.dispatchReceiverParameter!! - irThis = IrGetValueImpl(startOffset, endOffset, thisParameter.type, thisParameter.symbol, origin) - } - - while (innerClass != implicitThisClass) { - if (!innerClass.isInner) { - // Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is - - // should be transformed by closures conversion. - return expression - } - - val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass) - irThis = IrGetFieldImpl( - startOffset, endOffset, - outerThisField.symbol, outerThisField.type, - irThis, - origin - ) - - val outer = innerClass.parent - innerClass = outer as? IrClass ?: - throw AssertionError("Unexpected containing declaration for inner class ${innerClass.dump()}: $outer") - } - - return irThis - } - }) - } } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt index eb938d34798..a46429a6adf 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeInlineFunctionResolver.kt @@ -40,6 +40,8 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def SharedVariablesLowering(context).lower(body, function) + OuterThisLowering(context).lower(function) + LocalClassesInInlineLambdasLowering(context).lower(body, function) if (context.llvmModuleSpecification.containsPackageFragment(function.getPackageFragment()!!)) {