From ce0fb662c0721163510e665f6c8031b6b46621fc Mon Sep 17 00:00:00 2001 From: pyos Date: Mon, 11 Nov 2019 11:57:38 +0100 Subject: [PATCH] JVM_IR: fold inline lambdas when computing OUTERCLASS so that the enclosing method of objects defined inside lambdas is the one they are declared in. Note that this does not fix *all* enclosingInfo tests because JVM_IR currently follows the KT-28064 proposal, i.e. does not regenerate objects defined inside lambdas under any circumstances. For example, this causes test boxInline/enclosingInfo/inlineChain2.kt to fail because the enclosing method of objects is _2Kt.box instead of (non-existent in source code) `_2Kt$box$inlined$call$1.invoke` or whatever. What's more important is that OUTERCLASS no longer points to a non-existent `box$lambda-N` and therefore `.enclosingMethod` no longer throws. --- .../kotlin/backend/jvm/codegen/ClassCodegen.kt | 14 ++++++-------- .../backend/jvm/codegen/ExpressionCodegen.kt | 2 +- .../jvm/codegen/IrSourceCompilerForInline.kt | 8 ++++---- .../codegen/box/reflection/enclosing/kt6368.kt | 1 - .../boxInline/enclosingInfo/anonymousInLambda.kt | 2 -- .../codegen/boxInline/enclosingInfo/inlineChain.kt | 2 -- .../boxInline/signature/typeParameterInLambda.kt | 2 -- 7 files changed, 11 insertions(+), 20 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 20ee5258512..a916e7df9d5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -52,6 +52,7 @@ open class ClassCodegen protected constructor( internal val irClass: IrClass, val context: JvmBackendContext, private val parentClassCodegen: ClassCodegen? = null, + private val parentFunction: IrFunction? = null, private val withinInline: Boolean = false ) : InnerClassConsumer { private val innerClasses = mutableListOf() @@ -303,8 +304,8 @@ open class ClassCodegen protected constructor( } } - fun generateLocalClass(klass: IrClass, withinInline: Boolean): ReifiedTypeParametersUsages { - return ClassCodegen(klass, context, this, withinInline = withinInline || this.withinInline).generate() + fun generateLocalClass(klass: IrClass, parentFunction: IrFunction): ReifiedTypeParametersUsages { + return ClassCodegen(klass, context, this, parentFunction, withinInline = withinInline || parentFunction.isInline).generate() } private fun generateField(field: IrField) { @@ -404,12 +405,9 @@ open class ClassCodegen protected constructor( // or constructor, the name and type of the function is recorded as well. if (parentClassCodegen != null) { val outerClassName = parentClassCodegen.type.internalName - // TODO: Since the class could have been reparented in lowerings, this could - // be a class instead of the actual function that the class is nested inside - // in the source. - val containingDeclaration = irClass.symbol.owner.parent - if (containingDeclaration is IrFunction) { - val method = methodSignatureMapper.mapAsmMethod(containingDeclaration) + // TODO: LocalDeclarationsLowering could have moved this class out of its enclosing method. + if (parentFunction != null) { + val method = methodSignatureMapper.mapAsmMethod(parentFunction) visitor.visitOuterClass(outerClassName, method.name, method.descriptor) } else if (irClass.isAnonymousObject) { visitor.visitOuterClass(outerClassName, null, null) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 5e3d4976000..0afcd10780b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -556,7 +556,7 @@ class ExpressionCodegen( ) override fun visitClass(declaration: IrClass, data: BlockInfo): PromisedValue { - classCodegen.generateLocalClass(declaration, generateSequence(this) { it.inlinedInto }.any { it.irFunction.isInline }).also { + classCodegen.generateLocalClass(declaration, generateSequence(this) { it.inlinedInto }.last().irFunction).also { closureReifiedMarkers[declaration] = it } return immaterialUnitValue diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt index 02a2b306e23..3b54be07749 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt @@ -58,11 +58,11 @@ class IrSourceCompilerForInline( override val inlineCallSiteInfo: InlineCallSiteInfo get() { - //TODO: support nested inline calls + val root = generateSequence(codegen) { it.inlinedInto }.last() return InlineCallSiteInfo( - codegen.classCodegen.type.internalName, - codegen.signature.asmMethod.name, - codegen.signature.asmMethod.descriptor, + root.classCodegen.type.internalName, + root.signature.asmMethod.name, + root.signature.asmMethod.descriptor, //compilationContextFunctionDescriptor.isInlineOrInsideInline() false, compilationContextFunctionDescriptor.isSuspend diff --git a/compiler/testData/codegen/box/reflection/enclosing/kt6368.kt b/compiler/testData/codegen/box/reflection/enclosing/kt6368.kt index 0425b02da62..bfe7a75c733 100644 --- a/compiler/testData/codegen/box/reflection/enclosing/kt6368.kt +++ b/compiler/testData/codegen/box/reflection/enclosing/kt6368.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/compiler/testData/codegen/boxInline/enclosingInfo/anonymousInLambda.kt b/compiler/testData/codegen/boxInline/enclosingInfo/anonymousInLambda.kt index 6f16dbb7edb..358b6a8fb5c 100644 --- a/compiler/testData/codegen/boxInline/enclosingInfo/anonymousInLambda.kt +++ b/compiler/testData/codegen/boxInline/enclosingInfo/anonymousInLambda.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // TARGET_BACKEND: JVM // NO_CHECK_LAMBDA_INLINING // WITH_REFLECT diff --git a/compiler/testData/codegen/boxInline/enclosingInfo/inlineChain.kt b/compiler/testData/codegen/boxInline/enclosingInfo/inlineChain.kt index b5d6bf5a56c..0cd603b46d5 100644 --- a/compiler/testData/codegen/boxInline/enclosingInfo/inlineChain.kt +++ b/compiler/testData/codegen/boxInline/enclosingInfo/inlineChain.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // TARGET_BACKEND: JVM // FILE: 1.kt // WITH_REFLECT diff --git a/compiler/testData/codegen/boxInline/signature/typeParameterInLambda.kt b/compiler/testData/codegen/boxInline/signature/typeParameterInLambda.kt index f1db37c154a..255f1c05722 100644 --- a/compiler/testData/codegen/boxInline/signature/typeParameterInLambda.kt +++ b/compiler/testData/codegen/boxInline/signature/typeParameterInLambda.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // TARGET_BACKEND: JVM // FILE: 1.kt // WITH_REFLECT